问题描述
#include <stdio.h>int f(int, int, int){ return 0;}int main(){ return f(printf('a'), printf('b'), printf('c'));}
这是今天晚上遇到的腾讯在线笔试题目,问题是 “代码结果是什么?”这道题目结果是 cba 吗?为什么?
问题解答
回答1:拿这种未定义行为出题的腾讯也是够了。建议回答“这个结果是不是cba并不重要,重要的是日常工作中不要写出这样的代码 -- 尽量不要一行代码中写太多函数调用,除非是链式调用;对于有副作用的函数调用那必须要分开成多行来写。”
回答2:大部分的调用约定是从右向左入栈,即最右边的参数最先入栈,比如f(a, b, c),那么最先入栈的就c,其次是b,最后是a。具体到那你这里,首先入栈的是printf('c')的返回值,那么这里就会先对printf('c')进行一个调用。因此这段代码的函数调用顺序最终为printf('c'), printf('b'),printf('a'),f(1,1,1)。所以代码结果是cba。
回答3:C语言默认的Calling Convention是cdecl,也就是从右向左压栈。但是参数表求值顺序是未定义行为,函数参数表中的逗号并不是序列点。debug版的msvc和x86的gcc貌似都是从右到左求值的,但是据我所知Sparc上好像就是反过来的。至于优化过的release版则更无法确定了。
回答4:考得就是参数入栈方向,答案就是cba,上面解释的很好了。想说的是,我记得腾讯笔试题前面是有针对考题的保密协议的,追求技术问题的答案并没有错,但题主也要遵循你同意过的协议。
回答5:传参顺序不等于求值顺序,也就是说这道题目应该是错的,但是如果选的话建议选cba,因为调用约定多为从右向左穿参,出题者很可能误解为求值顺序也是如此
回答6:但是main函数里面返回的是f函数,而f函数的返回值是0,那么main函数返回值为什么不是0呢?