++,- -操作符的本质
C语言中的一些“小动作”
高级语言在运算中允许我们大跨度的运算。意思就是低级语言中需要好几步才能完成的一个运算,在高级语言中只要一步就可以完成了。
譬如C语言中的++和–运算符,在C中我们需要一个变量 i+1,我们只要写i++即可,这看起来虽然只有一句代码。但是我们知道编译器还是会吧C代码翻译成汇编语言的。
所以实际上 i++ 翻译到汇编阶段需要3步才能完成:
1. 从内存中读取i到寄存器
2. 对寄存器中的i进行加1
3. 将加1后的i写回内存中的i
C语言中只规定了++和–对应指令的相对执行次序,所以上面那3步实际上不一定按照这个次序来执行,不同编译器有不同的翻译次序。所以造成了多个++和–运算会产生不同结果。
++和–参与混合运算结果是不确定的。
示例代码:一对让人头疼的兄弟
#include <stdio.h>
int main ()
{
int i = 0 ;
int r = 0 ;
r = (i ++) + (i ++) + (i ++);
printf ( "i = %d\n" , i );
printf ( "r = %d\n" , r );
r = (++ i) + (++i ) + (++i );
printf ( "i = %d\n" , i );
printf ( "r = %d\n" , r );
return 0 ;
}
自己通过计算得出结果
i = 3
r = 0
i = 6
r = 15 (4 + 5 +6)GCC编译器得出结果
i = 3
r = 0
i = 6
r = 16 (5 + 5 +6)VS2010编译器得出结果
i = 3
r = 0
i = 6
r = 18 (6 + 6 + 6)
笔试面试中的“奇葩”题
#include <stdio.h>
int main ()
{
int i = 0 ;
int j = ++ i+++ i +++i ;
int a = 1 ;
int b = 4 ;
int c = a +++ b;
printf ( "i = %d\n" , i );
printf ( "j = %d\n" , j );
printf ( "a = %d\n" , a );
printf ( "b = %d\n" , b );
printf ( "c = %d\n" , c );
return 0 ;
}
输出结果
6: error: lvalue required as increment operand发现:++i+++i+++i;这句代码报错,那我们如何来分析这句代码呢?
面对++,–这种表达式,我们一般使用贪心法的阅读技巧
1. 编译器处理的每个符号应该尽可能多的包含字符
2. 编译器以从左到右的顺序一个一个尽可能多的读入字符
3. 当读入的字符不可能和已读的字符组成合法符号为止。
那么我们实际分析一下:++i+++i+++i;
1. 编译器会将字符读入到++i++才会结束,因为再读入一个+号将不合法。
2. 开始执行++i++,这句语句被翻译成(++i)++;
3. 得到1++。
常量无法自增,我们可以加入1++;语句验证一下。发现报的错误跟上面一模一样。
由此推论:a+++b将被翻译成(a++)+b;
问题:那么我们如何修改上面的代码避免错误呢?
解决方案有两种:
1. 在想要编译器停止读入字符的地方加入空格隔开
2. 用()吧你想要执行的语句括起来。
本文深入探讨了C语言中++和--运算符的工作原理及其在编译过程中的实现细节。通过对具体示例代码的分析,揭示了这些运算符在不同编译器下可能产生的差异及原因,并提供了避免常见陷阱的方法。

1038

被折叠的 条评论
为什么被折叠?



