论坛里经常会出现类似的提问:
int a=5;
printf("%d,%d,%d,%d",++a,a++,--a,a--);
为啥不是。。。为啥不是。。。而是。。。
有些初学者更是模糊,因为他们通过编译器编译得到的结果居然和论坛上有的结果不一样,和他们的预期也不一样。
1 > 这种题确实和编译器相关。有些人试图从得到的汇编来说,不要忘了汇编的代码也是经过编译器的编译逻辑决定的。经测试:上面的两行代码,vs2008 和 gcc得到是不一样的。gcc得到的结果与根据规则目测得到的结果一致。
那是不是根据这点就说明vs2008的编译器的实现不按照语法规则来编写 ?
2 > 不是。编译器是根据语法规则来实现的,只不过它还有“容错”和优化等功能,它考虑的问题比我们考虑到的还多。编译器、操作系统和搜索引擎号称最复杂的三大软件。虽然你有时写的代码有错误,但是依然得到预期的结果,像这种帖子也不少,“经典”之一的题目就是在函数里返回字符数组变量还是字符指针,有些编译器居然也给出预期结果。编译器确实很强大,你写的代码有缺陷,居然也会得到想要的结果。
但我们更强调的是规范:语法、实现和代码上的规范。
3 > 对于这种题型,我们都曾经不可避免遇到过。对于初学者,我建议不必要过多的纠结在这上面,特别是++i= ++i++i--之类的。你只要知道前缀和后缀的含义就行,前缀是先对变量自增再执行整个表达式,后缀是先执行表达式完了之后再执行变量的自增。而对于帖中的代码,你能答到函数的压栈顺序和自增自减的过程就可以了。
如果你想确定执行顺序和如果是按照规则来的话,可以用以下类似的方法:
记住千万不要拿反汇编得到的汇编来说事,汇编的代码也是经过编译器的编译译逻辑决定的,经过优化了的。
__inline int Geta(int *pa, int i);
int main()
{
int a = 5;
//printf("%d,%d,%d,%d\n", ++a, a++, --a, a--);
//这样就避免了优化,每次都是重新获取变量a的值,而且也确定了先后顺序。
printf("\n%d,%d,%d,%d\n", Geta(&a, 1), Geta(&a, 2), Geta(&a, 3), Geta(&a, 4));
return 0;
}
__inline int Geta(int *pa, int i)
{
switch (i)
{
case 4: printf("4th\n"); return (*pa)--;
case 3: printf("3th\n"); return --(*pa);
case 2: printf("2th\n"); return (*pa)++;
case 1: printf("1th\n"); return ++(*pa);
}
return 0;
}
以上只是对初学者或新学者的一点点建议,如有不妥之处,请海涵