字节顺序宏未正确定义[关闭]
Posted
技术标签:
【中文标题】字节顺序宏未正确定义[关闭]【英文标题】:Endianess macros not correctly defined [closed] 【发布时间】:2020-02-19 20:52:35 【问题描述】:我正在尝试编译 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
不知何故,这两个条件都满足了,导致编译失败(error: duplicate member 'th_off'
)。我写了一个测试C程序,好像三个宏定义不正确。
我尝试重新安装gcc
和g++
,并将它们降级到以前的版本。我还尝试重新安装 Linux 头文件。终于尝试用clang
编译了,还是不行。
我的两台测试计算机都运行 Ubuntu 19.10,它们的结果都是一样的。定义这些宏是否需要编译器标志或系统配置?
编辑:tcp.h
是系统标头。它不是我写的,它几乎是全新安装的 Ubuntu,标准安装为 build-essentials
。
编辑 2:我使用了一个测试程序,在这种情况下它可以正常工作。它显示little
:
#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
【问题讨论】:
__LITTLE_ENDIAN
和 __BIG_ENDIAN
是两个不同的常量,所以它们不能相等。在源代码的某个地方,它们已被重新定义。
@stark 他说它们根本没有定义,所以预处理器将它们全部视为0
。
如果你printf("BE: %d\nLE: %d\nBO: %d\n", __BIG_ENDIAN, __LITTLE_ENDIAN, __BYTE_ORDER)
你会得到什么
@stark 我看到它们在/usr/include/endian.h
中定义。 bits/endian.h
只是将__BYTE_ORDER
定义为其中之一。
我在我的问题中添加了测试程序结果
【参考方案1】:
在我的 Debian 系统上,__LITTLE_ENDIAN
和 __BIG_ENDIAN
在 /usr/include/endian.h
中定义。我相信此文件旨在跨架构通用。
__BYTE_ORDER
被定义为/usr/include/bits/endian.h
中的其中之一。我认为bits
目录包含特定于特定架构的标头。
tcp.h
包括<types.h>
,我认为应该间接包括这些并定义宏。我不确定为什么它没有发生在你身上。
【讨论】:
在我的系统上,netinet/tcp.h
包括 sys/types.h
,并且我看到的唯一包含到 endian.h
的内容是如果定义了 __USE_BSD
在我的 Ubuntu 19.10 机器上,如果定义了 __USE_MISC
,则包含 <endian.h>
。但是,如果 __USE_MISC
没有定义,那么 <netinet/tcp.h>
永远不会首先尝试声明有问题的结构。
这里一样,几乎整个标题都在#ifdef __USE_MISC
内。
在包含第一个标准标头后,可能会重新定义功能测试宏(或它们的 glibc 内部代理,如 __USE_MISC
),从而导致暴露的内容不一致。例如,如果 <sys/types.h>
已经包含在不公开 <endian.h>
的 FTM 中,那么稍后在包含 <netinet/tcp.h>
之前更改了宏,则如 OP 所见,字节序宏将丢失。【参考方案2】:
您可以使用 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预处理器中,两个不存在的宏是相等的。
来源:https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
【讨论】:
为什么系统头文件会有错误的宏?顺便说一句,我刚刚检查了我的 Debian 系统,和问题中的一样。 这些是 gcc 内置函数,而不是头文件常量 正如@Barmar 所说,我没有编辑文件,它是这样的...... "你可以使用 gcc builtins" - 注意这是一个系统头文件。更改系统头文件通常不是一个好主意。 @user3684240 OP 没有该选项。这是一个系统头文件。以上是关于字节顺序宏未正确定义[关闭]的主要内容,如果未能解决你的问题,请参考以下文章