为什么gcc不会抱怨htons()但是在使用-std = c99编译时抱怨getaddrinfo()?

时间:2016-09-09 10:47:13

标签: c posix c99

即使使用-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编译此代码。

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 addrinfogettaddrinfo的隐式声明是警告,而不是错误。未声明struct addrinfo 是错误。

结构在netdb.h中声明,但隐藏在ifdef __USE_POSIX下。有评论:

  来自POSIX.1g的

/ *扩展。 * /

ifdef没有此类htons