以下给定的程序正在运行而不包括<stdio.h>
?为什么这样做?
int main()
{
printf("integra");
return 0;
}
答案 0 :(得分:8)
printf()的定义存在于libc.so中,即使您不包含头文件,动态链接器也会处理它。在编译期间,printf()将是一个未定义的符号,它假定它可能稍后在libc中找到定义。头文件将只提供proto-type并禁止编译器(警告)声明原型的定义存在于glibc中。所以基本上,包含头文件只是为了确保我们的库中有定义,以帮助开发人员。
答案 1 :(得分:7)
在较旧的标准中,未声明的函数假定int
参数和返回值。您的char*
与int
具有相同的尺寸(32位),因此一切正常。
就是不要这样做。
答案 2 :(得分:5)
printf()仅在libc.so中定义
动态链接器将解析libc中的符号printf(),因为你没有包含它
对于每个程序,libc都是gcc的默认值
答案 3 :(得分:3)
正如Abi指出的那样,您的代码构建成功而不包含stdio.h,因为链接器默认为未定义符号(printf
)的系统std库。海湾合作委员会通常会警告你这类案件。
让test.c成为:
1: int main()
2: {
3: printf("test\n");
4: return 0;
5: }
在Mac OSX上使用GCC 4.2.1构建test.c:
$ gcc test.c
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
$ ./a.out
test
您可以通过指定GCC链接器选项-nostdlib
(或-nodefaultlibs
)以及-lgcc
来禁用此默认链接(如GCC手册所建议):
$ gcc -nostdlib -lgcc test.c
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
Undefined symbols:
"_puts", referenced from:
_main in cc3bvzuM.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
$
答案 4 :(得分:1)
一些(旧的?)编译器在调用函数之前不需要原型。
答案 5 :(得分:1)
当您使用尚未声明的函数时,编译器将假定此函数返回int
并采用未指定但固定数量的参数。
如果这个假设与函数的定义匹配,并且如果你提供的参数也匹配(模数默认参数提升)函数期望接收的参数,那么一切都很好。
如果假设不正确(例如printf
,这是一个可变函数),或者当参数不匹配时,结果是不确定的。未定义行为的一个令人讨厌的事情是,它似乎可以按预期工作。