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