Linux上的unistd.h和c99

这个简单的.c文件:

#include <unistd.h> void test() { char string[40]; gethostname(string,40); } 

…正常编译时,工作正常:

 $ cc -Wall -c -o tmp.o tmp.c $ 

…但在C99模式下编译时,会发出警告:

 $ cc -Wall -std=c99 -c -o tmp.o tmp.c tmp.c: In function `test': tmp.c:5: warning: implicit declaration of function `gethostname' $ 

结果.o文件是好的,并链接工程。 我只想摆脱这个警告。 我可以通过在我自己的.h文件中放入声明来以一种拙劣的方式实现这一点。

C99的含义是什么意思是unistd.h中的声明不包含在内? 这可以克服,而不放弃C99的好处?

我看到其他标准库的相同的问题。

您可能需要以特定方式定义一些宏来获取gethostname()的原型,

man gethostname

glibc的功能测试宏要求(请参阅feature_test_macros(7)):

  gethostname(): _BSD_SOURCE || _XOPEN_SOURCE >= 500 sethostname(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500) 

所以:

 #define _BSD_SOURCE #include <unistd.h> void test() { char string[40]; gethostname(string,40); } 

血淋淋的细节:

如果不指定-std-c99选项,那么features.h (隐式地包含在unistd.h )将默认设置_BSD_SOURCE ,使gethostname()的原型包含在内。 但是,指定-std=c99导致编译器自动定义__STRICT_ANSI__ ,这又会导致features.h不会定义_BSD_SOURCE ,除非您使用自己的特性宏定义(如上所述)强制它。

gethostname( )不是一个标准的C函数(在C99标准中没有提及),所以在编译到标准时,符号是没有被正确定义的。

如果你使用gcc工具链,使用-std=gnu99 ,你会得到你想要的行为。

或者,看<features.h> ,看起来你可以使用-D_GNU_SOURCE-D_XOPEN_SOURCE=500来获得所需的行为。

阅读man gethostname 。 它在功能测试宏要求中说,需要_BSD_SOURCE (或_XOPEN_SOURCE>500 )才能从unistd.h中提取gethostname。

接下来阅读man feature_test_macros 。 你会发现-std=c99打开__STRICT_ANSI__关闭 _BSD_SOURCE 。 这意味着你不能从unistd.h获得gethostname ,除非你再次定义_BSD_SOURCE 。 我通常将_GNU_SOURCE放置在我的命令行(即gcc -D_GNU_SOURCE -std=c99 file.c )上,这也是大部分的事情,它也打开了_BSD_SOURCE

PS手册页包含一个可打印当前ft-macros的示例程序。 您可以编译并运行一些编译器设置。