以便携式方式为位域分配最大值

时间:2016-03-18 11:56:59

标签: c++ portability bit-fields

说我有这样的位域:

struct SomeStruct {
    uint32_t first : 12;
    uint32_t second : 2;
    uint32_t third : 18;
};

SomeStruct obj;

我想分配

obj.second = 3;  // Actually, the maximum allowed value

实现这一目标的便携方式是什么? 我也不想明确使用已知的位域宽度。

我的代码

obj.second = std::numeric_limits<uint32_t>::max()

但与-Wbitfield-constant-conversion发出警告会发出警告并cpp reference states:

  

位字段的以下属性是实现定义的   使用a分配或初始化位字段所产生的值   值超出范围,或者增加超出其范围的位字段。

那么分配-1numeric_limits<uint32_t>::max()实际上是便携式还是有其他方式?

5 个答案:

答案 0 :(得分:2)

如果有两位,则最大值为2 2 -1。获得该值的一种简单方法是将1向左移动两步(给出2 2 )并减去1。

因此2位的最大值为(1U << 2) - 1

它可以在所有C编译器之间移植,并且编译器将能够优化操作,因此赋值仅适用于结果值。

答案 1 :(得分:2)

由于字段是无符号的,因此工作很简单:

obj.second = -1;

无符号算术可以很好地定义,即使对于位域也是如此。

答案 2 :(得分:1)

CWG 1816清楚地指出了一个不能用位字表示的值,结果值是实现定义的。

我担心,我不知道任何可移植的方式来实现你想要的东西。

答案 3 :(得分:0)

对于无符号整数类型:

unsigned char max = ~0;

在英语中,零补码将所有位设置为1,这是该类型的最大无符号值。

当您使用位域时,这种简单的方法可能对您不起作用。如果您使用:

struct SomeStruct {
    uint8_t first;
    uint8_t second;
    uint8_t third;
};

然后它可能是一个选项。

答案 4 :(得分:0)

最好的方法是分配-1 / -1L / ~0 / ~0LINT_MAX / LONG_MAX

但是这段代码依赖于当今计算机中整数的表示方式。这在任何地方都有效,但正式来自C标准规范是不可移植的。