求教: Linux 下一道 C 语言的经典面试题

2017-06-27 17:09:27 +08:00
 revotu

如果在 Linux 下使用 GCC 编译器执行下列程序,输出结果是什么?

#include<stdio.h> int main(){ int a=5; printf("%d %d %d",a++,a++,++a); return 0; }

原问题出处: http://www.revotu.com/advanced-c-interview-questions-and-answers.html

求详细讨论!!!

2077 次点击
所在节点    C
10 条回复
xss
2017-06-27 19:26:34 +08:00
你需要知道的:
1. c 语言的函数调用规则是 cdecl
2. cdecl 调用规则参数由右向左入栈

因此, 计算顺序由右向左, 即
++a
a++
a++

然后你还需要知道的, gcc 的行为:
所有具有前置自增 /减运算符位置的参数, 需要等所有前&后置运算完成之后, 才能决定.
所有具有后置自增 /减运算符位置的参数, 一旦前面的运算符完成, 值即可决定.

所以
++a => a=6 -> 决定了第二个参数为 6, 因为第二个参数之前, 再无前置运算, 且第二个参数为后置运算
a++ => a=7 -> 决定了第一个参数为 7, 因为第一个参数之前再无前置运算, 且第一个参数为后置运算
a++ => a=8 -> 所有运算完成, 所有具有前置运算符位置的参数, 全部等于这个值

因此, 输出为:
7, 6, 8

再看个复杂的:
printf("%d %d %d %d %d", a++, a++, a++, --a, ++a);

从右向左:
++a -> 6, 前面还有前置运算, 该位置参数的值未确定
--a -> 5, 还有前置, 该位置未确定值, 但是前一个参数是后置运算, 因此前面一个参数的值为 5
a++ -> 6, 这个位置的参数由上一步确定, 为 5, 同时决定下面的一个 a++的值为 6
a++ -> 7, 上一个 a++的值为 7
a++ -> 8, 所有自增操作运算完毕, 参数位置为前置自增的值可以定了, 为 8

因此, 输出为:
7 6 5 8 8
snnn
2017-06-27 20:02:21 +08:00
神经病。哪凉快哪躺着去
snnn
2017-06-27 20:03:41 +08:00
@xss 你第一句话就是错的。什么是 cdecl 啊?谁规定非得照它来啊。不这么来的多了去了。
billlee
2017-06-27 21:28:58 +08:00
在未定义行为上折腾是没有意义的
gnaggnoyil
2017-06-28 06:33:29 +08:00
按照 C99/11 标准,单个函数调用时各个参数的计算相互之间没有 sequenced before 关系,所以在这里有副作用的几条表达式直接炸成 UB.如果有谁想问 UB 的代码有什么外部可观测结果那么就直接打死,不要废话.
xss
2017-06-28 09:25:36 +08:00
@snnn 你行你上, 你解释. 连 libc 库是哪个调用约定都不知道, 我还能说啥.
gnaggnoyil
2017-06-28 13:32:06 +08:00
@xss 首先 libc 库多了去了谁一定要和你说的那样玩

其次,你是面向 C 和 POSIX 标准编程还是面向 glibc/Linux 的 ad hoc 实现编程?熟读语言标准的人都开始写 C 编译成浏览器 JavaScript 的编译器了,谭浩强式出身的人还在那里把 C 代码当作一个自己使用的特定平台的另一种语言的 trivial 对应.
xss
2017-06-28 14:13:57 +08:00
@gnaggnoyil 你要是说平台是 arm, mips 这种架构下的 libc. 好吧, 那我无话可说, 的确有可能并不遵守默认的函数调用标准. 但是就楼主这个情形来说, 明显是 x86 下的 glibc. 或者我这么说更确切一点(?): 目前所有 x86 架构下的 lts linux 发行版本, glibc 的调用标准都是 cdecl.
哪位能指教一下不是上述情况的 glibc ?
liuyao729
2017-08-10 11:46:58 +08:00
5 6 8
zmj1316
2017-09-03 08:01:19 +08:00
printf 这种不定长参数一般应该从左向右入栈吧,所以我猜 5 6 8

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/371442

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX