构造有符号的位域

时间:2017-01-30 17:15:41

标签: c++ bit-fields

下面我构建了一些我正在使用的代码字段代码的小例子。 在实现比较运算符时,我注意到它没有按预期工作。问题是-1似乎不小于1.

在考虑了一段时间之后,在我看来构造函数中的屏蔽有问题。

我添加了" aValue& MAX_VALUE"因为否则编译器会给出转换警告。但是,首先用MAX_VALUE屏蔽,然后转换为int32_t并不能给我正确的结果。

有谁知道如何解决这个问题? 当我在main()方法中编写minusOne.v = -1;时,我似乎得到了我期望的结果。但是我不确定如何在构造函数中编写它(没有获得转换警告)。

#include <iostream>
#include <cstdint>

using namespace std;

struct int27_t
{
    int32_t v:27;

    constexpr static int32_t MIN_VALUE = -(1L << 26);
    constexpr static int32_t MAX_VALUE = (1L << 26) - 1;
    constexpr static int32_t MASK = 0x7FFFFFF;

    int27_t() : v(0) {}

    explicit int27_t(int32_t aValue) : v(static_cast<int32_t>(aValue & MAX_VALUE)) {}

    friend bool operator<(const int27_t& aLhs, const int27_t& aRhs);
};

bool operator<(const int27_t& aLhs, const int27_t& aRhs)
{
    return aLhs.v < aRhs.v;
}

int main()
{
    int27_t minusOne{-1};
    int27_t plusOne{1};
    cout << "MAX_VALUE == " << int27_t::MAX_VALUE << " == 0x" << hex << int27_t::MAX_VALUE << dec << endl;
    cout << "-1 == " << minusOne.v << " == 0x" << hex << minusOne.v << dec << endl;
    cout << "-1 cast to int32_t: " << static_cast<int32_t>(minusOne.v) << " == 0x" << hex << static_cast<int32_t>(minusOne.v) << dec << endl;
    cout << "-1 < 1 ? " << (minusOne < plusOne) << endl;
    cout << endl;
}

节目输出

MAX_VALUE == 67108863 == 0x3ffffff
-1 == 67108863 == 0x3ffffff
-1 cast to int32_t: 67108863 == 0x3ffffff
-1 < 1 ? 0

1 个答案:

答案 0 :(得分:3)

布尔算术在签名类型上不起作用。 你只需& - 在构造函数中删除符号。

您的代码基本上存在四个问题:

  1. 不要对签名类型使用二进制算术。只是不要这样做。如果确实有必要,算术转换为unsigned(乘以-1并注意溢出),执行某些操作并返回签名算术
  2. 您依赖于已签名号码的特定表示。据我所知(这是关于签名类型的C99),该语言提供了三个不同的语言:符号和幅度一个补码二个补码< / em>,cf。 ISO / IEC 9899:TC2§6.2.6.2-2。
  3. 假设两个补码,几乎适用于所有最近的平台,您的MIN_VALUE将被关闭。
  4. 请不要使用位字段。几乎任何最近的架构都会将其扩展为某种字大小的类型。您可能不会获得任何麻烦,因为签名溢出是未定义的行为。因此,以这种方式限制签名类型的范围是没有意义的。