我正在使用仅有2KB SRAM的微控制器,并且迫切需要节省一些内存。试图找出如何使用位域将8个0
/ 1
值放入单个字节中,但无法完成它。
struct Bits
{
int8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};
int main(){
Bits b;
b.b0 = 0;
b.b1 = 1;
cout << (int)b.b0; // outputs 0, correct
cout << (int)b.b1; // outputs -1, should be outputting 1
}
是什么给出了?
答案 0 :(得分:113)
所有位域成员都是带符号的1位整数。在双补码系统中,这意味着它们只能代表0
或-1
。如果您需要uint8_t
和0
:
1
struct Bits
{
uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};
答案 1 :(得分:13)
谨慎之处 - 标准并没有真正实施位域的实现方案。不能保证Bits
将是1个字节,并且假设它完全可能更大。
在实践中,实际的实现通常遵循明显的逻辑,它几乎总是&#34;是1字节大小,但同样,没有要求保证。如果您想确定,可以do it manually。
BTW -1
仍为true
,但-1 != true
答案 2 :(得分:3)
如上所述,这些变量仅包含一个符号位,因此唯一可用的值为0
和-1
。
这些位域的更合适的类型是bool
。 C ++14§9.6/ 4:
如果值
true
或false
存储在任意大小的bool
类型的位字段中(包括一位位字段),则原始bool
值和比特字段的值应相等。
是的,std::uint8_t
将完成这项工作,但您也可以使用最合适的工作。你不需要像std::cout << (int)b.b0;
的演员表这样的东西。
答案 3 :(得分:0)
有符号和无符号整数就是答案。
请记住,信号只是对比特的解释,-1或1只是&#39; print&#39;序列化器解释&#34;变量类型&#34;,因为它是&#34;显示&#34;通过编译器来cout函数(查看运算符重载),该位是相同的,它的值也是(开/关) - 因为你只有1位。
不要关心这一点,但明确是一个好习惯,所以更喜欢用unsigned声明你的变量,它指示编译器在设置或获取类似于序列化器的值时安装正确的代码&#34;打印&#34; (COUT)。
<强>&#34; COUT&#34;操作员超载: &#34; COUT&#34;通过一系列函数工作,参数重载指示编译器调用哪个函数。因此,有两个函数,一个接收无符号和另一个签名,因此它们可以不同地解释相同的数据,您可以更改它,指示编译器使用强制转换调用另一个。见cout << myclass