【发布时间】:2013-01-30 09:04:22
【问题描述】:
我需要定义一个结构,它的数据成员大小为 2 位和 6 位。
我应该为每个成员使用char 类型吗?或者,为了不浪费内存,我可以使用:2\:6 之类的符号吗?
我怎样才能做到这一点?
我可以为 2 位或 6 位类型定义 typedef 吗?
【问题讨论】:
-
如何使用
std::bitset<char>??
我需要定义一个结构,它的数据成员大小为 2 位和 6 位。
我应该为每个成员使用char 类型吗?或者,为了不浪费内存,我可以使用:2\:6 之类的符号吗?
我怎样才能做到这一点?
我可以为 2 位或 6 位类型定义 typedef 吗?
【问题讨论】:
std::bitset<char> ??
你可以使用类似的东西:
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 可能并不适用于所有地方。
【讨论】:
这样的事情最好使用uint8_t。是的,使用bit fields:
struct tiny_fields
{
uint8_t twobits : 2;
uint8_t sixbits : 6;
}
不过,我认为您不能确定编译器会将其打包成一个字节。此外,在 struct 类型的值占用的字节内,您不知道这些位是如何排序的。如果您想要更多控制权,通常最好使用显式掩码。
【讨论】:
unsigned char 比使用uint8_t 更好。后者永远不能小于unsigned char,因此不会节省任何空间。它被允许根本不存在。使用uint8_t 只是静态断言CHAR_BIT == 8 的一种方式。
chars 慢。这是因为要写入位字段,您需要读取封闭字节,更新它,然后将其写回(读-修改-写循环)。不值得努力,除非你承受着极大的记忆压力。
&0x3f,只是它没有出现在你的源代码中:-) 当然,这仍然可能是使用它的充分理由,因为可读性对我来说很重要。
我个人更喜欢移位运算符和一些宏而不是位字段,因此编译器没有“魔法”。这是嵌入式世界的惯例。
#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 */
【讨论】: