我需要定义一个结构,其中包含大小为2位和6位的数据成员。
我应该为每个成员使用char
类型吗?或者,为了不浪费内存,我可以使用:2
\ :6
表示法吗?
我怎样才能做到这一点?
我可以为2或6位类型定义typedef吗?
答案 0 :(得分:7)
您可以使用以下内容:
typedef struct {
unsigned char SixBits:6;
unsigned char TwoBits:2;
} tEightBits;
然后使用:
tEightBits eight;
eight.SixBits = 31;
eight.TwoBits = 3;
但是,说实话,除非您必须遵守应用程序外部的打包数据,或者您处于非常内存受限的情况,否则这种内存节省通常不会值得。如果不必使用按位和位移操作来打包和解包数据,你会发现你的代码要快得多。
另请注意,使用_Bool
,signed int
或unsigned int
以外的任何类型都是实施的问题。具体而言,unsigned char
可能无处不在。
答案 1 :(得分:5)
最好使用uint8_t
来做这样的事情。是的,请使用bit fields:
struct tiny_fields
{
uint8_t twobits : 2;
uint8_t sixbits : 6;
}
我认为你不能确定编译器会将它打包成一个字节。此外,您无法在结构类型的值占用的字节内知道这些位的排序方式。如果你想要更多控制,通常最好使用显式掩码。
答案 2 :(得分:1)
我个人更喜欢移位运算符和一些宏而不是位字段,因此编译器没有“魔力”。这是嵌入式世界的通常做法。
#define SET_VAL2BIT(_var, _val) ( (_var) | ((_val) & 3) )
#define SET_VAL6BIT(_var, _val) ( (_var) | (((_val) & 63) << 2) )
#define GET_VAL2BIT(_var) ( (_val) & 3)
#define GET_VAL6BIT(_var) ( ((_var) >> 2) & 63 )
static uint8_t my_var;
<...>
SET_VAL2BIT(my_var, 1);
SET_VAL6BIT(my_var, 5);
int a = GET_VAL2BIT(my_var); /* a == 1 */
int b = GET_VAL6BIT(my_var); /* b == 5 */