我可以将2*12位无符号数字以3字节的形式存储在C++;使用位字段? 我在C++中使用一个LZW压缩应用程序。由于没有数据类型可以存储12位数字来表示4095以下的表元素,因此我认为可以将其中的2个NR存储为3个字节,然后将其作为包含2个无符号短成员的结构读取。有没有办法做到这一点,或者我应该使用unsigned short?这是我尝试过的,但它存储4个字节,因为有2个未签名的短成员 #define BITS 12 struct LZWStruct { unsigned short code1 : BITS; unsigned short code2 : BITS; }; int main() { LZWStruct test; test.code1 = 144; test.code2 = 233; FILE* f = fopen("binary.bin", "wb"); fwrite(&test, sizeof(test), 1, f); fclose(f); }

我可以将2*12位无符号数字以3字节的形式存储在C++;使用位字段? 我在C++中使用一个LZW压缩应用程序。由于没有数据类型可以存储12位数字来表示4095以下的表元素,因此我认为可以将其中的2个NR存储为3个字节,然后将其作为包含2个无符号短成员的结构读取。有没有办法做到这一点,或者我应该使用unsigned short?这是我尝试过的,但它存储4个字节,因为有2个未签名的短成员 #define BITS 12 struct LZWStruct { unsigned short code1 : BITS; unsigned short code2 : BITS; }; int main() { LZWStruct test; test.code1 = 144; test.code2 = 233; FILE* f = fopen("binary.bin", "wb"); fwrite(&test, sizeof(test), 1, f); fclose(f); },c++,file,compression,byte,C++,File,Compression,Byte,从中,多个相邻位字段通常打包在一起。可以强制大小为零的特殊未命名位字段分解填充。它指定下一个位字段从其分配单元的开头开始。使用sizeof验证结构的大小 然而,确切的打包可能取决于平台和编译器。如果数据稍后由同一个程序加载,或由某些密切相关的程序加载,则问题可能会小一些,但对于某些通用格式而言,这可能是一个问题。您的问题标题和问题正文是两个不同的问题,答案不同 不,您绝对不能在四个字节(32位)中存储3*12位无符号数字(36位) 是的,您可以在三个字节(24位)中存储两个12位数字(24位)

从中,多个相邻位字段通常打包在一起。可以强制大小为零的特殊未命名位字段分解填充。它指定下一个位字段从其分配单元的开头开始。使用sizeof验证结构的大小


然而,确切的打包可能取决于平台和编译器。如果数据稍后由同一个程序加载,或由某些密切相关的程序加载,则问题可能会小一些,但对于某些通用格式而言,这可能是一个问题。

您的问题标题和问题正文是两个不同的问题,答案不同

不,您绝对不能在四个字节(32位)中存储3*12位无符号数字(36位)

是的,您可以在三个字节(24位)中存储两个12位数字(24位)

<>从C++继承的C++中的位字段不能确切地保证结构中的位是如何填充的,因此您无法知道结构中的三个字节有哪些数据。您应该简单地使用shift和or运算符将它们放入整数中。然后您将确切地知道要写入文件的三个字节

然后,为了便于移植,特别是不依赖于机器的endianess,还应该使用shift运算符从整数写入字节。如果使用指向整数的指针进行写入,则它将无法移植

在您的示例中,您可能已经尝试了
fwrite(&test,3,1,f)
,如果编译器将代码放在
test
的低位,并且如果您的机器是little endian,那么它可能会起作用。否则,不会

因此,要可靠地做到这一点:

输入一个整数:

unsigned short code1;
unsigned short code2;
uint32_t test = (code1 & 0x3ff) | ((uint32_t)(code2 & 0x3ff) << 12);
如果愿意,可以跳过中间步骤:

putc(code1, f);
putc(((code1 >> 8) & 0xf) | (code2 << 4), f);
putc(code2 >> 4, f);
putc(代码1,f);
putc((代码1>>8)和0xf)|(代码2>4,f);

(在上面我保证我只使用
&
运算符存储每个代码的低位12位,以防低位12位以上的位不为零。如果您确定代码值小于4096,则可以删除上面的
&
操作。)

而不是“有办法吗?”最好问“怎么做?”“有办法吗?”的答案通常只是“是”,但这不是您想要得到的答案位字段的详细信息是特定于编译器的,并且(很可能)可能不可移植,并且不能保证编译器会以您想要的方式进行位旋转(在您关心这些详细信息的情况下)。如果您自己进行掩蔽和移位,则可以保证布局。尽管您可能还需要担心endian问题。但无法保证位字段在结构中的布局。因此,您的结构可能仍然大于4字节。示例显示,clang、msvc和gcc在sp的结构中都使用6字节说明。3*12位是36位。4*8位是32位。无论使用何种语言,都不适合。或者问题标题与实际问题不同步?因为这似乎只涉及存储两个这样的数字……是的,这是我想要的,谢谢,但我如何才能做反向操作(读取这些字节并将它们分配给2个无符号短变量)?我将把这作为读者的练习。如果您了解这是如何工作的以及
|
和“&”操作,这将很容易。
putc(code1, f);
putc(((code1 >> 8) & 0xf) | (code2 << 4), f);
putc(code2 >> 4, f);