即使使用-std=c99
进行编译,以下程序也会编译并运行正常。
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
printf("%d\n", htons(1));
}
这是输出。
$ gcc -std=c99 foo.c && ./a.out
256
但是以下程序会导致警告和错误。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
struct addrinfo *res;
getaddrinfo("localhost", NULL, NULL, &res);
printf("%d\n", res->ai_flags);
}
以下是警告和错误。
$ gcc -std=c99 bar.c
bar.c: In function ‘main’:
bar.c:9:5: warning: implicit declaration of function ‘getaddrinfo’ [-Wimplicit-function-declaration]
getaddrinfo("localhost", NULL, NULL, &res);
^
bar.c:10:23: error: dereferencing pointer to incomplete type
printf("%d\n", res->ai_flags);
为什么编译器不会抱怨htons()
但是在使用getaddrinfo()
编译时抱怨-std=c99
?
我正在使用Debian 8.3系统上的gcc 4.9.2编译此代码。
答案 0 :(得分:5)
来自Linux man pages for glibc:
POSIX.1-2001。
htons()
POSIX.1-2001,POSIX.1-2008。 getaddrinfo()函数已记录在案 在RFC 2553中。
由于glibc 2.22:_POSIX_C_SOURCE&gt; = 201112L
Glibc 2.21及更早版本:_POSIX_C_SOURCE
要获取getaddrinfo()
的原型,您需要在包含标题之前指定要使用的POSIX版本,例如:
#define _POSIX_C_SOURCE 201112L
RFC 2553为套接字接口添加了IPv6支持。添加意味着添加了新的结构。
由于并非所有的plkatforms都能立即实现新的东西,因此需要指定更改内容所需的接口版本。 htons
在所有版本中都是相同的,因此它并不关心您请求的版本。由于RFC 2553,getaddrinfo
已更改,因此您需要指定您希望/(可以处理)更改后的版本。
如评论中所述,_POSIX_C_SOURCE所需的值因平台而异。似乎对于RHEL6上的gcc,指定_POSIX_SOURCE或_POSIX_C_SOURCE&gt; = 1就足够了。
如果有人能够确认_POSIX_SOURCE是否是在任何POSIX系统上获取getaddrinfo
原型的可移植方式,那将是很棒的。
答案 1 :(得分:2)
问题不在getaddrinfo
- 它位于struct addrinfo
。 gettaddrinfo
的隐式声明是警告,而不是错误。未声明struct addrinfo
且 是错误。
结构在netdb.h
中声明,但隐藏在ifdef __USE_POSIX
下。有评论:
来自POSIX.1g的/ *扩展。 * /
ifdef
没有此类htons
。