未定义的行为:i=i++;

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_42948022/article/details/102734495

分析:

i=i++;

1:	先算出左边的值,置为0;

2:	执行i++;的+1操作.

3:	将左边的值赋给i.

2和3在不同编译器中经过优化后有不同的执行顺序。所以执行后i可能是0,可能是1.
能运行不代表是正确的。
这种写法,是C标准严格禁止的。
c标准里,叫做未定义行为。

i++产生的原因:

在c/c++中,为了少写一行代码、或者为了和某条汇编语句对应,这颗语法糖就被加进去了。因为和正规意义上的表达式不同,这种东西的副作用发生时机,会深刻改变程序的执行结果。

编译时的优化:

当编译器为c表达式生成机器码时,会偷偷做很多优化动作,以尽量加快程序执行速度。
怎么保证这些优化动作是对的、没有优化出错误呢?这就要靠C标准来规范了。
C标准委员:不规定i++的正确结果是什么样子(这就是“未定义行为”的含义),
编译器折腾成啥都没关系——哪怕你去格他的硬盘,也是符合标准的。

序列点

序列点就是类似c/c++里面, ; 这样的符号,(函数中参数分割的逗号不算)
每一个序列点结束时,必须有一个确定的状态,但可以不限定每个序列中的过程。
			//如果限定了执行细节,那么在某些机器上可能就会变得很慢、
			//或者导致一些优化算法失效,加大编译器实现的难度。
也就是说允许编译器可以随意改序列中的执行顺序以实现算法上的优化。

但,对i=i++来说,如果不规定每一拍内部的执行细节,那么就可以有很多很多种不同结果。

结果:

最终,C/C++委员会的决定是:任何类似的写法都不予支持。
如果有人这么做了,那么编译器输出任何结果都是合法的。

按照规定,这种非法代码,执行结果是无法确定的。编译器为其生成任何代码都合法。
所以,现实是,不同编译器、同一个编译器的不同版本、相同版本编译器使用不同编译参数,结果都可能不同。

猜你喜欢

转载自blog.csdn.net/qq_42948022/article/details/102734495
i++