我需要在0到15之间存储一个C值,4位就足够了。我怎么才能有一个4位的变量?空间是一个约束
答案 0 :(得分:7)
考虑使用char
。是的,它是8位,但你可以使用位移运算符(<<
和>>
)来存储其他4位的值。
修改:根据以下评论,unsigned char
实际上优于char
,以避免符号位出现问题。
答案 1 :(得分:4)
您可以使用bitfield来存储您的4位,但是,除非您在结构中将它们中的几个相邻,否则不会节省任何空间而不是将值存储在一个字节中。
答案 2 :(得分:3)
你实际上不能有一个4位变量,但你可以有8位变量来存储两个4位值,但是你必须使用temp访问它们,这意味着你不能保存任何空间,除非你有两个以上:
uint8_t var_both;
uint8_t temp = (var_both >> 4) & 0x0F; // For first value
temp = var_both & 0x0F; // For second value
答案 3 :(得分:2)
正如Chris Lutz指出的那样,您可以通过添加冒号及其大小来定义变量使用的位数:unsigned char myOneBitVariable:1;
以及您的情况'unsigned char MyFourBitVariable:4'。我想指出极其困难这是为什么你应该避免。
大多数现代编译器会在结构中为变量对齐空间。今天最常见的情况是4个字节甚至8个字节,但这在不同平台和编译器之间有所不同。某些编译器允许您指定数据及其成员的对齐方式。在GCC上,关键字为__attribute__((aligned(x)))
,在MSVC上为__declspec(align(x))
。在大多数情况下,您还需要指定编译器应该打包多少结构。 MSVC具有#pragma pack(x)
指令:http://msdn.microsoft.com/en-us/library/2e70t5y1(VS.80).aspx。您还可以在此处阅读有关MSVC对齐的信息:http://msdn.microsoft.com/en-us/library/83ythb65(VS.80).aspx。 GCC有自己的实现名为__attribute__ ((__packed__)
,您可能需要搜索它。
使用Microsoft编译器的一个例子没有给你你想要的东西:
#ifndef _MSC_VER
#error This alignment solution / packing solution is only valid on MSC
#endif /* ifndef _MSC_VER */
#define M_ALIGN(x) __declspec(align(x))
struct S64Bits
{
unsigned char MyOneBitVariable:1;
int My32BitInt;
};
// MSVC specific implementation of data-packing in a type.
#pragma pack(1)
struct S32Bits
{
D_ALIGN(1) int My16BitVariable:16;
D_ALIGN(1) unsigned char Padding8Bits;
D_ALIGN(1) unsigned char MyOneBitVariable1:1;
D_ALIGN(1) unsigned char MyOneBitVariable2:1;
D_ALIGN(1) unsigned char MyOneBitVariable3:1;
D_ALIGN(1) unsigned char MyOneBitVariable4:1;
D_ALIGN(1) unsigned char MyFourBitVariable:4;
};
#pragma pack(pop)
'sizeof(S64Bits)'应该是8,它是。 'sizeof(S32Bits)'应为4,不是。在msvc上,后者是6个字节。该行为也是特定于编译器的,并且通常具有编译器唯一的指令。这种行为几乎从未给你你想要的东西。我经常使用宏来确保我需要的结构确实是:
#define TEST_TYPE_SIZE(Type, Size) assert(sizeof(Type) == Size);
我会在我的所有数据类型下面使用,我会尝试指定它们的确切大小。但是,依赖于sizeof(mystructure)之外的任何大小的结构都是编码,可能导致难以调试错误。 Alignment-compiler指令最适合用于将数据与高速缓存行大小和类似的效率问题对齐。
Karl Bielefeldt提供了一个很好的自然解决方案,可以使用位移操作将4位值存储到uint8中,而不是使用它们。
答案 4 :(得分:0)
半字节的术语是半字节。所以这里:
struct two_nibbles {
unsigned a :4;
unsigned b :4;
}
您必须将两个变量命名为x.a
和x.b
(但将x
更改为其他变量),但您将节省一点空间。您可能想要检查一下 - 我认为编译器会确保sizeof(struct two_nibbles) == sizeof(char)
但它可能不会,因此您可能需要添加更多的半字节以使其值得腾出空间。
答案 5 :(得分:0)
您是否想要获取4位值的地址?如果是这样,您需要将它们存储在“正确”的数据类型中,例如char。