C++ 未正确定义Endianess宏

C++ 未正确定义Endianess宏,c++,c,linux,gcc,clang,C++,C,Linux,Gcc,Clang,我正在尝试编译grpc,其中一个目标使用/usr/include/netinet/tcp.h,其中包含以下内容: # if __BYTE_ORDER == __LITTLE_ENDIAN uint8_t th_x2:4; /* (unused) */ uint8_t th_off:4; /* data offset */ # endif # if __BYTE_ORDER == __BIG_ENDIAN uint8_t t

我正在尝试编译
grpc
,其中一个目标使用
/usr/include/netinet/tcp.h
,其中包含以下内容:

# if __BYTE_ORDER == __LITTLE_ENDIAN
        uint8_t th_x2:4;        /* (unused) */
        uint8_t th_off:4;       /* data offset */
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
        uint8_t th_off:4;       /* data offset */
        uint8_t th_x2:4;        /* (unused) */
# endif
不知何故,这两个条件都满足了,导致编译失败(
错误:复制成员'th_off'
)。我写了一个测试C程序,这三个宏似乎没有正确定义

我试图重新安装
gcc
g++
,并将它们降级到以前的版本。我还尝试重新安装Linux头文件。我最后尝试用
clang
编译,但也不起作用

我的两台测试计算机运行的是Ubuntu19.10,结果是相同的。是否需要编译器标志或系统配置来定义这些宏

编辑:
tcp.h
是一个系统头。我没有写它,它几乎是Ubuntu的新安装,标准安装为
build-essentials

编辑2:我使用了一个测试程序,它在本例中正常工作。它显示

#include <iostream>
#include <netinet/tcp.h>

int main() {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    std::cout << "little\n";
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
    std::cout << "big\n";
#endif
}
#包括
#包括
int main(){
#如果字节顺序=小字节

std::cout您可以使用gcc内置:

# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        uint8_t th_x2:4;        /* (unused) */
        uint8_t th_off:4;       /* data offset */
# endif
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        uint8_t th_off:4;       /* data offset */
        uint8_t th_x2:4;        /* (unused) */
# endif
在c预处理器中,两个不存在的宏是相等的


来源:

在我的Debian系统上,
\uuu LITTLE\u ENDIAN
\uu BIG\u ENDIAN
/usr/include/ENDIAN.h
中定义。我相信该文件是跨架构的通用文件

\u BYTE\u ORDER
/usr/include/bits/endian.h
中被定义为其中之一。我认为
bits
目录包含特定于特定体系结构的标题


tcp.h
包括
,我认为应该间接地包括它们并定义宏。我不知道为什么这不会发生在你身上。

\uuu LITTLE\u ENDIAN
是两个不同的常量,所以它们不可能都相等。在源代码的某个地方,它们被重新定义了。@stark他说它们根本没有定义,因此预处理器将它们都视为
0
。如果
printf(“BE:%d\nLE:%d\nBO:%d\n”,“BIG\u ENDIAN”,“LITTLE\u ENDIAN”,“BYTE\u ORDER”)会得到什么
@stark我看到它们在
/usr/include/endian.h
bits/endian.h
中定义,只是在其中一个定义了
\uuuuu BYTE\u ORDER
。我在问题中添加了测试程序结果,为什么系统头文件会有错误的宏?顺便说一句,我刚刚检查了我的Debian系统,它与问题中的一样。这些是gcc内置的s、 不是头文件constantsAs@Barmar说,我没有编辑该文件,它是这样的…“你可以使用gcc内置”-请注意,这是一个系统头文件。更改系统头文件通常不是一个好主意。@user3684240 OP没有该选项。它是一个系统头文件。在我的系统上,
netinet/tcp.h
包含
sys/types.h
,我在这里看到的
endian.h
的唯一包含是if
\u USE\u BSD
在我的Ubuntu19.10机器上,如果定义了
\uuuuUse\uMisc
,则会包含
。但是如果没有定义
\uUse\uMisc
,则
从一开始就不会试图声明有问题的结构。同样,几乎整个标题都在
\ifdef\uUse\uMisc
中。很可能有什么东西在重新定义特性t宏(或它们的glibc内部代理,如
\u使用\u MISC
)包含第一个标准标头后,会导致显示内容不一致。例如,如果未公开的FTM中已包含
,则随后在包含
之前更改了宏,endian宏将丢失,如OP所示。