user-0 提问: 小白问一个只有5行程序的题，求大神解我好几天谜团

回复:
user: user-0
content: 引用 17 楼 cuipy 的回复:这个要说到整数的++运算的问题了； int a=2; a++;   //  返回值为a的当前值，这一行结束的时候a的值加1； ++a;   //  a的值加1，并且返回新的值。    其实第二种 ++a 这样的，应该是这一行语句执行完毕后才返回，并不是++a 之后马上返回；  因此 你说的那个题里面： add(n++,++n,n++)   第二个实参要等到另外n++都执行完毕后，才返回，这时候就成了n+1 又+1 ，然后中间的++n才返回，就成了好像中间的参数最后计算一样。   不知道说清楚没有？  哇塞！！你这个回答真好！终于懂了

user: user-1
content: 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

user: user-0
content: 好吧，目前还看不懂汇编代码，等以后学习一下汇编，再去看看运行时的反汇编，应该会懂。谢谢你了

user: user-2
content: 感觉只有面试题或者谭的书上才会出这种难受的题

user: user-3
content: 引用 14 楼 chenzheng1030 的回复:怎么会很混乱？参数之间的逗号相当于一个序列点，编译器到这里的时候会把++之后的新值写入到变量a的地址。 add(a++, ++a, a++); 我觉得汇编伪代码是长这样的: ;压第一个参数，最右边的 LOD a MOV a REG1 INC a STR a ;压第二个参数，中间的 LOD A INC a STR a MOV a REG2 ;压第三个参数，最左边的 LOD a MOV a REG3 INC a STR a 谁说参数之间的逗号是序列点了？

user: user-4
content: 这个要说到整数的++运算的问题了； int a=2; a++;   //  返回值为a的当前值，这一行结束的时候a的值加1； ++a;   //  a的值加1，并且返回新的值。    其实第二种 ++a 这样的，应该是这一行语句执行完毕后才返回，并不是++a 之后马上返回；  因此 你说的那个题里面： add(n++,++n,n++)   第二个实参要等到另外n++都执行完毕后，才返回，这时候就成了n+1 又+1 ，然后中间的++n才返回，就成了好像中间的参数最后计算一样。  不知道说清楚没有？

user: user-0
content: 引用 12楼东边一耳 的回复:这个没有副作用，所有的++都已经有逗号分隔开了。 这个问题主要是要考虑到函数参数的压栈顺序，而这个压栈顺序是跟ABI相关的，不同的编译器在不同的平台和操作系统下面实现不同的ABI，楼主的测试结果来看，应该是从右往左入栈。 add(a++, ++a, a++);         <------<------<--- 因为从右往左，所以楼主自己就知道该怎么判断了。  真正未定义的是这样子的： a++ + ++a，这才是坑爹的玩意根据压栈顺序来讲，无论传入几个a++，结果都是可以推出来的。重点在于  传入++a的时候，结果很混乱，并不是简单的先把当前a的值自增然后进栈。在出栈的时候，++a还会有影响。我就是弄不清这个++a到底是怎么影响的。

user: user-5
content: 怎么会很混乱？参数之间的逗号相当于一个序列点，编译器到这里的时候会把++之后的新值写入到变量a的地址。 add(a++, ++a, a++); 我觉得汇编伪代码是长这样的: ;压第一个参数，最右边的 LOD a MOV a REG1 INC a STR a ;压第二个参数，中间的 LOD A INC a STR a MOV a REG2 ;压第三个参数，最左边的 LOD a MOV a REG3 INC a STR a

user: user-5
content: 这个没有副作用，所有的++都已经有逗号分隔开了。 这个问题主要是要考虑到函数参数的压栈顺序，而这个压栈顺序是跟ABI相关的，不同的编译器在不同的平台和操作系统下面实现不同的ABI，楼主的测试结果来看，应该是从右往左入栈。 add(a++, ++a, a++);         <------<------<--- 因为从右往左，所以楼主自己就知道该怎么判断了。  真正未定义的是这样子的： a++ + ++a，这才是坑爹的玩意

user: user-6
content: 各个厂商设计得都不一样，你用codeblocks和vc6运行都会不同。 怎么可能出这种题，退一万步说即使面试这种题，你直接指出来，估计这样分更高哦

user: user-7
content: 编译器不同，可能会产生不同的计算值。 在实际编写程序的过程中，应当尽量避免此类运算的使用【一般也不会用到】， 而使用没有编译歧义的代码。

user: user-1
content: 关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

user: user-0
content: 引用 6楼yelinCoder 的回复:拒绝回答此类面试题，赞同一楼大哥回答。有的时候吧，只是单纯的想知道

user: user-8
content: 拒绝回答此类面试题，赞同一楼大哥回答。

user: user-9
content: 出这样题目的人，拉出去轮X十分钟再说！！！！

user: user-0
content: 引用 1楼战在春秋 的回复:压栈顺序和编译器的实现相关，书上愿意出这样的题，源自谭浩强。 实际上这类题没有太大意义，在这上面纠结几天时间，更是极不划算。  在C99标准中属于不确定行为(undefined behavior)  引用The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified.  具体到这个题目，如果是老师出的，问问老师怎么解释，如果是书上的，应该有解答，实在不行，邮件询问作者。视频在讲函数参数的运算顺序，这是我自己引申的，在Linux下和vs2015下运算结果是一样的。这种代码一般也不写，就是可能会出在企业的笔试题里

user: user-0
content: 引用 2楼自信男孩 的回复:不论前++还是后++都会有副作用； 像这种：add(a++, ++a, a++);这种问题不建议继续讨论了。以后要避免写这样的代码；这是有可能出在面试的笔试题上的，自己肯定不会写这样的代码

user: user-10
content: 不论前++还是后++都会有副作用； 像这种：add(a++, ++a, a++);这种问题不建议继续讨论了。以后要避免写这样的代码；

user: user-11
content: 压栈顺序和编译器的实现相关，书上愿意出这样的题，源自谭浩强。 实际上这类题没有太大意义，在这上面纠结几天时间，更是极不划算。  在C99标准中属于不确定行为(undefined behavior)  引用The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified.  具体到这个题目，如果是老师出的，问问老师怎么解释，如果是书上的，应该有解答，实在不行，邮件询问作者。