在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,该标准不允许位域跨越底层类型的字边界。