在MSVC中强制未对齐的位域打包
我有一个位域结构,最多可加48位。 在GCC上,这正确地导致了6字节结构,但在MSVC中,结构出现了8个字节。 我需要找到一些方法来强制MSVC正确打包结构,这既适用于互操作性,也适用于在内存关键环境中使用。
下面看到的结构由三个15位数字,一个2位数字和一个1位符号组成。 15 + 15 + 15 + 2 + 1 = 48,理论上它应该适合六个字节,对吗?
struct S { unsigned short a:15; unsigned short b:15; unsigned short c:15; unsigned short d:2; unsigned short e:1; };
但是,在GCC和MSVC上对此进行编译会导致sizeof(S) == 8
。 考虑到这可能与对齐有关,我尝试在结构声明之前使用#pragma pack(1)
,告诉编译器返回到byte,而不是int,boundary。 在海湾合作委员会, 这工作 ,导致sizeof(S) == 6
。
但是,在MSVC05上,sizeof仍然是8,即使设置了pack(1)
! 在阅读了这个其他的SO答案后 ,我尝试用unsigned char
替换unsigned short d
,用bool
替换unsigned short e
。 结果是sizeof(S)
== 7 !
我发现如果我将d分成两个一位字段并将它们夹在其他成员之间,那么结构最终会正确打包。
struct S { unsigned short a:15; unsigned short dHi : 1; unsigned short b:15; unsigned short dLo : 1; unsigned short c:15; unsigned short e:1; }; printf( "%d\n", sizeof(S) ); // "6"
但是像这样分裂是很麻烦的,以后在我必须处理结构时会给我带来麻烦。 有没有什么方法可以强制MSVC将这个结构打包成6个字节,就像GCC一样?
实现定义了如何将字段放置在结构中。 Visual Studio会将连续的位域放入底层类型(如果可以),并浪费剩余空间。 ( VS中的C ++位字段 )
如果你使用类型“unsigned __int64”来声明结构的所有元素,你将获得一个sizeof(S)= 8的对象,但最后两个字节将是未使用的,前六个将包含格式的数据你要。
或者,如果您可以接受某些结构重新排序,这将起作用
#pragma pack(1) struct S3 { unsigned int a:15; unsigned int b:15; unsigned int d:2; unsigned short c:15; unsigned short e:1; };
我不这么认为,我认为MSVC的行为实际上是正确的,GCC偏离了标准。
AFAIK,该标准不允许位域跨越底层类型的字边界。