【问题标题】:constructing signed bit-fields构造有符号位域
【发布时间】:2017-01-30 17:15:40
【问题描述】:

下面我构建了一个我正在处理的使用位字段的代码的小示例。 在实现比较运算符时,我注意到它没有按预期工作。问题在于 -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

【问题讨论】:

  • 这里真的没有理由使用位域。在现代平台上,该结构无论如何都会被四舍五入到 32 位。同样,屏蔽和two's-complement 不兼容,符号位会被撕掉。
  • @tadman,我理解使用 MAX_VALUE 撕裂符号位进行掩蔽。但是我该如何解决呢?使用 MASK 值进行屏蔽会导致转换警告。
  • 我认为@kamajii 有一些很好的建议,我鼓励你遵循它。

标签: c++ bit-fields


【解决方案1】:

布尔算术不适用于有符号类型。 你只是 &amp;-ing 离开你的构造函数中的标志。

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

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

【讨论】:

  • 读到这里,我的所作所为看起来真的很糟糕,我会考虑采取一种没有位域的不同方法。我的目标不是获得良好的性能,而是模拟一个不同的设备,该设备在位数上有一定的限制(所以是模拟,而不是性能)。但这对你的论点并不重要。我会考虑如何改变它。
  • 你确定我的MIN_VALUE 是一个人吗?对我来说似乎是正确的,应该还有一个负值。
猜你喜欢
  • 2012-11-12
  • 1970-01-01
  • 2019-07-11
  • 2010-09-14
  • 2015-09-08
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2019-05-13
相关资源
最近更新 更多