【问题标题】:Bitfields in C++C++ 中的位域
【发布时间】:2010-08-07 08:54:37
【问题描述】:

我有以下自学代码:

#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(包括在内),field2k 从 0 到 15。为什么会出现这样的结果?也许应该全部为零?

【问题讨论】:

    标签: c++ bit-fields


    【解决方案1】:

    你的领域溢出了。我们以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.
    

    你的其他领域也一样。

    【讨论】:

      【解决方案2】:

      您有这些结果是因为分配溢出了每个位域。

      变量filed1 是 3 位,但 8 需要 4 位才能呈现(1000)。低三位全为零,所以filed1为零。

      对于filed2,17用10001表示,但filed2只有四位。低四位代表值 1。

      最后,对于k,18用10010表示,但k只有四位。低四位代表值 2。

      我希望这有助于解决问题。

      【讨论】:

        【解决方案3】:

        在 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] 这对于 signed 类型是不正确的,在这种类型中它是未定义的,然后会发生什么。

        【讨论】:

        • 为什么对有符号类型没有定义? int k:4 将保持 -8 到 7,分配 18 仍将产生 2,而分配 15 将产生 -1。我假设二进制补码算术,毕竟这是最常见的。任何其他算术仍然可以很好地定义,只是不一样。
        • C++ 开发的一个目标是尽可能地与底层机器的特性无关。因此,标准文档不对有符号整数的表示或其行为做出任何假设:可以是 1 补数,并且它们可能会在溢出时 trap
        • 这当然很重要。比如还有人写x+1&lt;x之类的溢出检查,不知道按照规则可以用'false'代替
        猜你喜欢
        • 2010-09-06
        • 2023-03-10
        • 1970-01-01
        • 2010-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多