我有一个预定义的结构(实际上是几个),其中变量跨越32位字边界.在Linux(以及使用GCC的Windows)中,我能够使用'attribute((packed))'将我的结构打包到正确的大小.但是我无法使用VC++和#pragma pack以相同的方式工作.
使用GCC,返回正确的6字节大小:
struct { unsigned int a : 3; unsigned int b : 1; unsigned int c : 15; unsigned int troubleMaker : 16; unsigned short padding : 13; } __attribute__((packed)) s;
使用VC++,这将返回不正确的8字节大小
#pragma pack(push) #pragma pack(1) struct { unsigned int a : 3; unsigned int b : 1; unsigned int c : 15; unsigned int troubleMaker : 16; unsigned short padding : 13; } s; #pragma pack(pop)
我可以通过手动将"troubleMaker"分割成边界来实现工作,但我不愿意.有任何想法吗?
我建议不要使用特定于供应商的C语言扩展来匹配设备或网络位格式.即使您使用一系列每个供应商的语言扩展来排列字段,您仍然需要担心字节顺序,并且您仍然需要一个需要额外指令才能访问的结构布局.
您可以使用标准化的C API字符串和内存复制函数以及Posix hton和ntoh函数编写符合C99标准的程序,该程序可以在任何体系结构或主机上以最高速度和缓存效率运行.
一个好的做法是使用已发布标准的以下函数:
C99: memcpy(), Posix: htonl(), htons(), ntohl(), ntohs()
更新:这里有一些代码应该在任何地方都一样.如果Microsoft 仍然没有为C99实现它,或者只是对int size做出通常的假设,那么你可能需要
从这个项目中获取.
#include#include #include #include #include struct packed_with_bit_fields { // ONLY FOR COMPARISON unsigned int a : 3; unsigned int b : 1; unsigned int c : 15; unsigned int troubleMaker : 16; unsigned short padding : 13; } __attribute__((packed)); // USED ONLY TO COMPARE IMPLEMENTATIONS struct unpacked { // THIS IS THE EXAMPLE STRUCT uint32_t a; uint32_t b; uint32_t c; uint32_t troubleMaker; }; // NOTE NOT PACKED struct unpacked su; struct packed_with_bit_fields sp; char *bits = "Lorem ipsum dolor"; int main(int ac, char **av) { uint32_t x; // byte order issues ignored in both cases // This should work with any environment and compiler memcpy(&x, bits, 4); su.a = x & 7; su.b = x >> 3 & 1; su.c = x >> 4 & 0x7fff; memcpy(&x, bits + 2, 4); su.troubleMaker = x >> 3 & 0xffff; // This section works only with gcc memcpy(&sp, bits, 6); printf( sp.a == su.a && sp.b == su.b && sp.c == su.c && sp.troubleMaker == su.troubleMaker ? "conforming and gcc implementations match\n" : "huh?\n"); return 0; }
位域的对齐和排序是众所周知的特定于实现的.这是很多安全声明一个正常的整型字段,并使用口罩和位内操纵"位域"(|&^)运营商.