24小时热门版块排行榜    

查看: 1896  |  回复: 32

sunchuanxi

新虫 (初入文坛)

送红花一朵
引用回帖:
7楼: Originally posted by 吟游诗人丶夏 at 2016-04-25 23:06:46
百度的答案。。。当i=1时。。j=(++i)+(++i)+(++i)=(((++i)+(++i))+(++i))
计算机在计算j=(a+b)+(c+d)+(e+f)先计算(a+b)+(c+d),并把结果存储(例如:存储在j中),然后再计算j+(e+f)=j;
所以计算机先计算了两个++i( ...

谢谢

发自小木虫Android客户端
11楼2016-04-26 09:04:26
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

sunchuanxi

新虫 (初入文坛)

引用回帖:
8楼: Originally posted by 吟游诗人丶夏 at 2016-04-25 23:09:38
同理最后一段运用到你这个式子上也一样也是21吧,。转自新浪爱问。。鱼鹰
...

按照这种算法是22

发自小木虫Android客户端
12楼2016-04-26 09:28:19
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

virtualzx

木虫 (著名写手)

引用回帖:
12楼: Originally posted by sunchuanxi at 2016-04-26 09:28:19
按照这种算法是22
...

那个百度的解释是错的

发自小木虫IOS客户端
13楼2016-04-26 10:05:04
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

stdlib_h

新虫 (初入文坛)

【答案】应助回帖

感谢参与,应助指数 +1
不能说的到21、22 是编译器bug,这个和编译器实现有关,我测试过。
本地iMac,结果 21 (clang)
ideone和cpp.sh、Linux上、FreeBSD以及其他所有gcc版本上结果均为:22
ideone:  http://ideone.com/m1XCZV  
cpp.sh :  http://cpp.sh/5qcsc  

我本地iMac测试结果:
gcc -v
Apple LLVM version 7.3.0 (clang-703.0.29)
add.c:4:5: warning: multiple unsequenced modifications to 'j' [-Wunsequenced]
        q=(++j)+(++j)+(++j);
           ^     ~~
1 warning generated.
21

我在一台FreeBSD服务器上测试结果:
[xxxx@FreeBSD ~/work]$ gcc -v
gcc version 4.2.1 20070831 patched [FreeBSD]
[xxxx@FreeBSD ~/work]$ gcc add.c -o add && ./add
22

一台Linode VPS Debian系统 上测试结果:
xxxx@(none):~/work$ gcc -v
gcc version 4.7.2 (Debian 4.7.2-5)
xxxx@(none):~/work$ gcc add.c -o add && ./add
22

最神奇的Microsoft的VC++ 结果竟然为24 :
下面网站提供 GCC、VC、CLANG 三个主流C编译器结果在线测试:
http://rextester.com/l/c_online_compiler_gcc   
得到的结果GCC: 22 , VC: 24,CLANG: 21
VC(C) 24:      http://rextester.com/FUOOR65113
Clang(c) 21:  http://rextester.com/TVO11176  
GCC(c) 22:    http://rextester.com/OFERJ85936  

当然我本人也认为结果应该为21,所以再碰到这类题目,离开编译器 就是刷流氓,你可以带着上面这个网址,狠狠的扇出题人的脑袋,直到扇的他吐血。

其实这类题目根本毫无意义,谁会在项目里这么写呢?
没有什么问题是递归解决不了的,如果有,那就用循环🔄--OCaml
14楼2016-04-26 11:51:36
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

ooliu12345

银虫 (小有名气)

讨论这个问题没有任何意义,因为语言并没有给出式子应该有的计算顺序,任何式子都有一个顺序点问题,所以这个结果与编译器的规定有关,如果你查看汇编代码,可以发现不同的编译器编译出来的汇编代码不同。

发自小木虫Android客户端
15楼2016-04-26 12:09:39
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

virtualzx

木虫 (著名写手)

【答案】应助回帖

按照c++规定的解析顺序规则,应自左向右逐个计算每个++i表达式的值并相加,每次取值前i的值递增1,因此得到21。
然而C++是十分重视速度和优化的语言,C++标准允许编译器在不改变结果的情况下任意变换表达式的结构。但是当变量的值在表达式内变化时,编译器很难优化,所以C++标准第五章第四条规定,在任何两个顺序点之间(这里分号;就是顺序点。其他顺序点包括比较算符和不同变量的初始化分隔符等),任何标量变量的值最多改变一次。
编译器是无法在编译时判断变量改变次数的,因此你的语句并不会被拒绝,但是它还是可以以最多变化一次为假设对表达式变形,而这是不正确的假设,因此这时得到的值就不一定和标准顺序规定的值一致,不同编译器都会得到不同结果,甚至不同版本结果都会不同(vc++里甚至按照debug和release编译得到的结果都不一定一样)
究其原因,是因为这个语句本身已经违反了C++标准。其他语言如C#就规定编译器必须严格遵守求值顺序不能随意变换,但速度会受影响

发自小木虫IOS客户端
16楼2016-04-26 12:10:43
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

wshy1126

新虫 (正式写手)

除非非得用这种表达式,不然纠结这样的问题没多大意义。

发自小木虫Android客户端
17楼2016-04-26 12:14:52
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

hxd_yi

金虫 (小有名气)

跟编译器有关,龙书上应该有讲。这个题适合在C++中作为反面典型讲,不要写这种不确定性的语句。

发自小木虫Android客户端
18楼2016-04-26 12:23:50
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

sunchuanxi

新虫 (初入文坛)

19楼2016-04-27 08:43:25
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

virtualzx

木虫 (著名写手)

【答案】应助回帖

引用回帖:
14楼: Originally posted by stdlib_h at 2016-04-26 11:51:36
不能说的到21、22 是编译器bug,这个和编译器实现有关,我测试过。
本地iMac,结果 21 (clang)
ideone和cpp.sh、Linux上、FreeBSD以及其他所有gcc版本上结果均为:22
ideone:  http://ideone.com/m1XCZV  
cpp. ...

24是因为vc认定三个++i的值是一样的,因为根据§5/4可以推测出所有左递增/递减算符可以提取到表达式之前,又递增递减算符都可以提取到表达式之后的结论,因此VC将这一表达式转化为
++i; ++i; ++i;
i+i+i

”谁会写出这样的语句”?其实几乎每个人都会,而且也是个重要的问题。这不只是表达式写法,而是C/C语音不完全解析顺序导致的。其他面向对象语言几乎都是可以不含糊的解析顺序的。这不只是++算符而已,如果任何表达式里有两个以上有side effect的函数,都有可能导致问题。这类含糊表达式非常常见,比如printf(..., x,f(x))这样简单的语句,如果f函数改变x的值,不同编译器都可能会给出不同的结果。
其他的例子,比如f(getc(), getc()),还有i=i++,还有以至于obj.f1()+obj.f2()这样常见的表达式,如果两个函数都有副作用,结果就可能因编译器不同而不同!

而这都是§5/4的结果。其实解析求值顺序不是不可能的,但是C本着速度第一的原则有意放松了标准

一个解决办法是,写程序时保证任何有返回值的函数没有副作用;而有副作用的都写成过程;但这样引入很大难度,实际上任何程序员都会写出很多依照标准含糊的C++表达式的。这也是提出C#语言的一个主要的原因之一。

发自小木虫IOS客户端
20楼2016-04-27 09:42:59
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 sunchuanxi 的主题更新
信息提示
请填处理意见