APUE 第 7 章说此代码段将退出,退出代码不是 0(示例中为 13)。但它在我的电脑上以代码 0 退出:
#include <stdio.h>
main()
{
printf("hello, world\n");
}
编译运行环境:
Darwin cuixiaochens-MacBook-Pro.local 17.4.0 Darwin 内核版本 17.4.0:Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64 x86_64
海湾合作委员会版本:
♪ apue.3e git:(master) gcc -v
配置为:--prefix=/Library/Developer/CommandLineTools/usr--with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM 版本 9.0.0 (clang-900.0.39.2)
目标:x86_64-apple-darwin17.4.0
线程模型:posix
安装目录:/Library/Developer/CommandLineTools/usr/bin
最佳答案
APUE 试图说明一个真实的现象,并且通过修改后的程序仍然可以观察到该现象。
通常,当声明返回值的函数(即 void
以外的返回类型)以“从末尾掉落”返回时,其返回值是“不确定的”,并且观察到的程序该值具有“未定义的行为”。出现未定义行为的一种常见方式是函数的返回值等于函数内最后一次调用的返回值,因为该值仍在返回值寄存器中。 APUE 试图通过从 main
的末尾掉落来证明这一点,但自从 C99 以来,有一个关于从 main
的末尾掉落的特殊规则,它表示这表现为 -如果 main
正确地返回了 0。许多编译器甚至在他们的 C89 模式中应用这个规则,因为在 C89 中它是未定义的,所以他们可以做任何他们喜欢的事情。
所以,要观察APUE要你观察的现象,你需要使用main
以外的函数,还需要采取措施防止过程间分析,比如将程序拆分成两个翻译单元,然后不使用链接时优化。
/* file1.c */
#include <stdio.h>
int print_hello(void)
{
printf("hello world\n");
}
/* file2.c */
#include <stdio.h>
extern int print_hello(void);
int main(void);
{
int n = print_hello();
printf("print_hello returned %d\n", n);
return 0;
}
分别编译每个文件,例如cc -c
然后将它们链接在一起作为第三个操作。在我的电脑上,使用我的编译器打印
hello world
print_hello returned 12
请记住这个程序确实有未定义的行为。在具有不同调用约定(例如 SPARC)的计算机上,它可能会打印出垃圾编号;如果我允许过程间优化发生,编译器可能会推断出程序没有未定义行为的唯一方法是它从不运行,因此根本没有代码。
(如果从未使用过 print_hello
返回的值,则程序不会有未定义的行为。这是语言中的另一种特殊情况,为了向后兼容在 void
返回类型之前编写的代码是可能的。)
关于c++ - APUE 第 7 章中的 hello world 以代码 0 退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52569139/