foo*_*foo 7 c endianness data-structures
我需要将位域结构从little-endian转换为big-endia架构.如果我只是交换结构元素,那么在字节边界中会出现问题的最佳方法是什么?
Ex结构是:
struct {
unsigned int b1:1;
unsigned int b2:8;
unsigned int b3:7;
unsigned int b4:8;
unsigned int b5:7;
unsigned int b6:1;
};
Run Code Online (Sandbox Code Playgroud)
您可以使用32位整数,并使用and-和bitshift运算符从中提取信息.有了这个,你可以简单地使用htonl(host-to-network,long).网络字节顺序是大端.
这不会像位字段那样优雅,但至少你会知道你拥有什么,而不必担心编译器填充你的结构.
小智 6
处理器字节顺序与位字段排序无关.在同一台计算机上使用两个编译器很可能使用相反的位域排序.所以,鉴于此:
union {
unsigned char x;
struct {
unsigned char b1 : 1;
unsigned char b2 : 7;
};
} abc;
abc.x = 0;
abc.b1 = 1;
printf( "%02x\n", abc.x );
Run Code Online (Sandbox Code Playgroud)
除非您碰巧有详细的文档,否则了解是否打印出01或80的唯一方法就是尝试它.
在将代码从MIPS移植到Linux/x86的项目中,我们确实喜欢这样.
struct {
#ifdef __ONE_ENDIANESS__
unsigned int b1:1;
unsigned int b2:8;
unsigned int b3:7;
unsigned int b4:8;
unsigned int b5:7;
unsigned int b6:1;
#define _STRUCT_FILLED
#endif /* __ONE_ENDIANESS__ */
#ifdef __OTHER_ENDIANESS__
unsigned int b6:1;
unsigned int b5:7;
unsigned int b4:8;
unsigned int b3:7;
unsigned int b2:8;
unsigned int b1:1;
#define _STRUCT_FILLED
#endif /* __OTHER_ENDIANESS__ */
};
#ifndef _STRUCT_FILLED
# error Endianess uncertain for struct
#else
# undef _STRUCT_FILLED
#endif /* _STRUCT_FILLED */
Run Code Online (Sandbox Code Playgroud)
宏__ONE_ENDIANESS__
和__OTHER_ENDIANESS__
是适合我们使用,所以你可能需要考虑其是否适合你的编译器...
foo*_*foo -3
为了实现这一点,我终于得到了一个解决方案(一些来自上面 epatel 的解决方案)。这是我从 x86 转换到 Solaris SPARC 的情况。
我们需要首先交换传入的结构,然后以相反的顺序读取元素。基本上在查看了结构如何对齐之后,我发现字节序和位序的字节顺序都发生了变化。这是一个伪代码。
struct orig
{
unsigned int b1:1;
unsigned int b2:8;
unsigned int b3:7;
unsigned int b4:8;
unsigned int b5:7;
unsigned int b6:1;
};
struct temp
{
unsigned int b6:1;
unsigned int b5:7;
unsigned int b4:8;
unsigned int b3:7;
unsigned int b2:8;
unsigned int b1:1;
}temp;
func (struct orig *toconvert)
{
struct temp temp_val;
//Swap the bytes
swap32byte((u32*)toconvert);
//Now read the structure in reverse order - bytes have been swapped
(u32*)&temp_val = (u32 *)toconvert;
//Write it back to orignal structure
toconvert->b6=temp_val.b6;
toconvert->b5=temp_val.b5;
toconvert->b4=temp_val.b4;
toconvert->b3=temp_val.b3;
toconvert->b2=temp_val.b2;
toconvert->b1=temp_val.b1;
Run Code Online (Sandbox Code Playgroud)
}
经过一些实验,我发现这种方法仅在元素完全填充结构时才有效,即没有未使用的位。