GCC 4中的in6_addr

时间:2013-09-20 17:28:48

标签: c linux gcc

我看到如下代码:(我正在处理的项目中的legecy代码)

#if __GNUC__ > 3
    .ipv6_addr = {.__in6_u = {.__u6_addr32 = {0, 0, 0, 0}}}
#else
    .ipv6_addr = {.in6_u = {.u6_addr32 = {0, 0, 0, 0}}}
#endif

其中“ipv6_addr”是in6_addr中struct的类型。如果__GNUC >我不明白为什么其成员in6_u会改为“ in6_u” 3.

我的问题是:为什么/当GCC版本可能影响struct in6_addr中字段的名称?

感谢。

更新:我的主机系统有GCC 4.1.2,但in6_addr定义为:

in /usr/include/netinet/in.h

/* IPv6 address */
struct in6_addr
  {
    union
      {
        uint8_t u6_addr8[16];
        uint16_t u6_addr16[8];
        uint32_t u6_addr32[4];
      } in6_u;
#define s6_addr                 in6_u.u6_addr8
#define s6_addr16               in6_u.u6_addr16
#define s6_addr32               in6_u.u6_addr32
  };

gcc版本是:

$/usr/bin/gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)

1 个答案:

答案 0 :(得分:2)

此处关注的结构定义struct in6_addr来自C运行时库(在<netinet/in.h>中)。 C运行时库通常与正在使用的操作系统紧密耦合,但正在使用的C 编译器。对于将__GNUC__定义为任何值的C编译器尤其如此(其中至少有三个:GCC,clang和icc);这些编译器设计用于许多不同的操作系统和运行时。因此,原则上,测试__GNUC__并不会告诉您有关运行时结构定义的任何有用信息。

我怀疑这个“遗留代码”的作者在两个不同的Linux发行版上进行了测试,注意到__GNUC__的值与<netinet/in.h>的内容之间的意外相关性,并没有费心寻找一种更正确的方法来编译代码。

您应该用以下内容替换整个条件:

.ipv6_addr = IN6ADDR_ANY_INIT;

相关标准(POSIX.1-2008 spec for <netinet/in.h>)要求宏IN6ADDR_ANY_INIT可用作类型in6_addr变量的初始值设定项,将该变量设置为IPv6通配符地址,是全位零。因此,它将具有相同的效果,而根本不需要任何#ifdef


为了说明此处#if __GNUC__ > 3是错误的测试,以下是struct in6_addr的三个不同定义,所有定义均来自您可能合理遇到的系统 both {{ 1}}和__GNUC_==3(3.x系列现在变得有些老了,但我还是时不时地遇到它。)

GNU libc 2.17

__GNUC__==4

NetBSD 6.1

struct in6_addr
  {
    union
      {
        uint8_t __u6_addr8[16];
#if defined __USE_MISC || defined __USE_GNU
        uint16_t __u6_addr16[8];
        uint32_t __u6_addr32[4];
#endif
      } __in6_u;
  };

Windows 7(官方SDK;反过来不提供struct in6_addr { union { __uint8_t __u6_addr8[16]; __uint16_t __u6_addr16[8]; uint32_t __u6_addr32[4]; } __u6_addr; /* 128-bit IP6 address */ }; ):

netinet/in.h