2

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

#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”是 struct in6_addr 的类型。我不明白如果 __GNUC > 3,为什么它的成员 in6_u 会变成“in6_u”。

我的问题是:为什么/何时 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)
4

1 回答 1

2

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

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

你应该用这个替换整个条件:

.ipv6_addr = IN6ADDR_ANY_INIT;

IN6ADDR_ANY_INIT相关标准(POSIX.1-2008 规范<netinet/in.h>)要求该宏可用作类型变量的初始化程序,将该变量in6_addr设置为 IPv6 通配符地址,即全位为零。所以它完全不需要任何#ifdefs 就可以达到同样的效果。


为了说明#if __GNUC__ > 3在此处应用的测试是错误的,这里有 3 个不同的定义struct in6_addr,所有这些定义都取自您可能会合理遇到的系统 __GNUC_==3__GNUC__==4(3.x 系列现在有点过时了,但我仍然不时遇到它到时间)。

GNU libc 2.17

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;
  };

NetBSD 6.1

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 */
};

Windows 7(官方SDK;反常不提供netinet/in.h):

struct in6_addr {
    union {
        UCHAR     Byte[16];
        USHORT    Word[8];
    } u;
};
于 2013-09-20T17:53:07.163 回答