位域的字节顺序是实现定义的。有没有办法在编译时检查是否通过一些宏或其他编译器标志,gcc的bitfield字节顺序实际上是什么?
换句话说,给出了类似的东西:
struct X {
uint32_t a : 8;
uint32_t b : 24;
};
有没有办法让我在编译时知道,a
是X
中的第一个还是最后一个字节?
答案 0 :(得分:4)
在Linux系统上,您可以查看__BYTE_ORDER
宏,看看它是__LITTLE_ENDIAN
还是__BIG_ENDIAN
。虽然这不具有权威性,但在实践中它应该有效。
提示这是正确的方法是在netinet / ip.h中定义struct iphdr
,这是针对IP头的。第一个字节包含两个4位字段,这些字段实现为位域,因此顺序非常重要:
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/*The options start here. */
};
答案 1 :(得分:0)
当位域为8位的倍数时,似乎体系结构的字节序无关紧要。
请参见here [godbolt.org]
在此示例中,我选择了arm体系结构,因为它支持大小端字节,并且比较差异也很容易。
请注意,无论体系结构是大字节序还是小字节序,在两种情况下,8位字段都在结构的开头。
我在godbolt上测试了所有可以为is_8bit_tag_at_start函数生成可读汇编代码的编译器,它们似乎都返回true。