我有以下自学代码:
#include <iostream>
using namespace std;
struct bitfields{
unsigned field1: 3;
unsigned field2: 4;
unsigned int k: 4;
};
int main(){
bitfields field;
field.field1=8;
field.field2=1e7;
field.k=18;
cout<<field.k<<endl;
cout<<field.field1<<endl;
cout<<field.field2<<endl;
return 0;
}
我知道unsigned int k:4
表示k是4位宽,或最大值15,结果如下。
2
0
1
例如,filed1
可以是0到7(包含),field2
和k
从0到15.为什么会有这样的结果?也许应该全部为零?
答案 0 :(得分:9)
你的田地里满是你。我们以k
为例,它是4位宽。正如你所说,它可以保存0到15之间的值,二进制表示为
0 -> 0000
1 -> 0001
2 -> 0010
3 -> 0011
...
14 -> 1110
15 -> 1111
所以当你指定18时,有二进制表示
18 -> 1 0010 (space added between 4th and 5th bit for clarity)
k
只能保存低四位,所以
k = 0010 = 2.
同样适用于其他字段。
答案 1 :(得分:4)
您有这些结果,因为分配溢出了每个位域。
变量filed1
是3位,但8位需要4位(1000)。低三位全为零,因此filed1
为零。
对于filed2
,17由10001表示,但filed2
仅为4位。低四位代表值1.
最后,对于k
,18由10010表示,但k
仅为4位。低四位代表值2.
我希望这有助于澄清事情。
答案 2 :(得分:1)
在C ++中,任何 unsigned 类型都会在你达到它的上限时回绕[1]。当您定义4位的位域时,您存储的每个值也会被包裹。大小为4的位域的可能值为0-15。如果您存储'17',那么您将换行为'1',对于'18',您再将其换成'2'。
在数学上,包装值是以目标类型的可能值的模数为基础的原始值:
对于大小为4的位域(2 ** 4个可能的值):
18 % 16 == 2
17 % 16 == 1
对于大小为3的位域(2 ** 3个可能的值):
8 % 8 == 0.
[1]对于已签名的类型,情况并非如此,因为未定义会发生什么。