我如何在C中表示位信息?

时间:2010-08-07 06:31:06

标签: c

我需要在0到15之间存储一个C值,4位就足够了。我怎么才能有一个4位的变量?空间是一个约束

6 个答案:

答案 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.ax.b(但将x更改为其他变量),但您将节省一点空间。您可能想要检查一下 - 我认为编译器会确保sizeof(struct two_nibbles) == sizeof(char)但它可能不会,因此您可能需要添加更多的半字节以使其值得腾出空间。

答案 5 :(得分:0)

您是否想要获取4位值的地址?如果是这样,您需要将它们存储在“正确”的数据类型中,例如char。