关于C的表达式未定义行为

关于C语言的表达式的未定义行为有很多,这里讨论讨论其中之一,请参考如下的代码:

int i = 6;

int k = (++i) + (++i) + (++i);

我相信很多初学者看到这段代码,也可能感到很纠结,这段代码的变量k的值,到底是多少?其实这段代码是无定义行为的代码,他的行为取决于编译器.

这个表达式是有副作用的,因为,在序列点之间,变量的值不能保证行为唯一性,也就是说第一次执行完++i,他在内存中的值可能改变。同一个表达式中,对于变量或者对象的多次使用,不应该改变其值,否则,预期的结果就无法保证。

下面,通过在VC平台下,这段代码的执行的结果是 k = 25,那么,为什么会是这样的结果呢?

我们想知道底层到底做了什么?所以,我们可以通过对应的汇编代码来了解底层到底做了什么?

4:       int i = 6;
00401028   mov         dword ptr [ebp-4],6    
5:       int k = (++i) + (++i) + (++i);
0040102F   mov         eax,dword ptr [ebp-4] 
00401032   add         eax,1                              
00401035   mov         dword ptr [ebp-4],eax  
00401038   mov         ecx,dword ptr [ebp-4] 
0040103B   add         ecx,1                             
0040103E   mov         dword ptr [ebp-4],ecx 
00401041   mov         edx,dword ptr [ebp-4] 
00401044   add         edx,dword ptr [ebp-4] ; 通过上面的汇编代码 edx = i = 8将edx的值与变量i的值相加  edx = 16
00401047   mov         eax,dword ptr [ebp-4] ; 再次将i的值赋值给eax
0040104A   add         eax,1                             ;  eax自增1  eax = 9
0040104D   mov         dword ptr [ebp-4],eax ; eax -> i   i = 9
00401050   add         edx,dword ptr [ebp-4]  ;  edx = 16  i = 9   所以,edx = 25
00401053   mov         dword ptr [ebp-8],edx ;  edx -> k  所以,k = 25
第一,首先明白++i 是先加后用,i++先用后加

其实,这个是VC编译器优化的结果,当执行int k = (++i) + (++i) + (++i)表达式的时候,首先,将前面的两个++i优化,将i的值自增2 i = 8 假设 m = (++i) + (++i) ,那么, k = m+(++i) 然后执行后面的++i的时候,i = 9 所以,结果是 k = 16 + 9 = 25. 

通过,上面的分析,你应该明白未什么这样的结果?但是,根据ANSI C标准给出的规定,这样的代码却是无定义的行为,即UB(Undefined Behavior)

包含多个不确定的副作用的代码的行为总是被认为未定义。

简单而言, “多个不确定副作用” 是指在同一个表达式中使用导致同一对象修改两次或修改以后,又被引用的自增, 自减和赋值操作符的任何组合 甚至都不要试图探究这些东西在你的编译器中是如何实现的(这与许多C 教科书上的弱智练习正好相反, 正如K&R 明智地指出, “如果你不知道它们在不同的机器上如何实现, 这样的无知可能恰恰会有助于保护你。”)

通过以上的解释,我相信你应该明白其中的道理,关于平时写代码必须符合标准的规范性。不然,将会降低代码的可移植性。这篇文章的目的是为了帮助更多被这样问题困扰的初学者,以上都是我的一些个人见解,希望能对你们有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值