C ++ 14中的有符号位字段

时间:2015-11-15 18:57:49

标签: c++ c++14 bit-fields

我相信在C ++ 14之前,声明为int的结构的位字段仍被解释为signedunsigned,解释是实现定义的。参考:http://en.cppreference.com/w/cpp/language/bit_field

在C ++ 14中仍然如此吗?即,下面的代码是否保证按照有意的方式工作?

#include <iostream>

struct X
{
    int f:3;
};

int main() 
{
    X x;
    x.f = -2; // is this going to be indeed signed? It seems so.
    std::cout << x.f << std::endl; // displays -2
}

1 个答案:

答案 0 :(得分:5)

根据C ++ 11标准§9.6/ p3比特字段[class.bit] Emphasis Mine ):

  

位字段不应是静态成员。位域应具有   积分或枚举类型(3.9.1)。 它是实现定义的   是否是明文(既未明确签名也未签名)charshort,   intlonglong long位字段已签名或未签名。 bool值   可以成功地存储在任何非零大小的位字段中。该   运营商地址&amp;不应该应用于位域,所以那里   没有指向位域的指针。非const引用不受约束   到一个位域(8.5.3)。 [注意:如果初始化器为参考   类型const T&amp;是一个左值,引用一个位字段,即引用   绑定到临时初始化以保存的值   位字段;引用不直接绑定到位字段。看到   8.5.3。 - 后注]

所以你对第一部分是正确的。确实,直到C ++ 14,声明为signed的结构的位字段仍然被解释为signedunsigned,解释是实现定义的。

正如@T.C在本评论中已经提到的那样。提及该问题的缺陷报告DR739DR675。导致C ++ 14标准中的以下解决方案:

措辞“它是实现定义的是普通(既未明确签名也未签名)charshortintlong或{{1} } bit-field有符号或无符号。“,已删除,现在C ++ 14的措辞是:

  

位字段不应是静态成员。位域应具有   积分或枚举类型(3.9.1)。 bool值可以成功   存储在任何非零大小的位域中。运营商的地址&amp;   不应该应用于位域,因此没有指针   位字段。非const引用不应绑定到位字段   (8.5.3)。 [注意:如果初始化器为const T&amp;类型的参考   是一个引用位字段的左值,引用绑定到a   临时初始化以保存位字段的值;该   引用不直接绑定到位字段。见8.5.3。 - 注意   ]

同样在§C.1.8第9章:类[diff.class] 中添加了以下部分:

  

9.6

     

更改: plain int类型的位字段已签名。

     

理由:将签名选择留给实施可能会导致定义不一致   模板专业化。为了保持一致性,不依赖性地消除了实现自由度   类型也是。

     

对原始功能的影响:该选择是在C中实现定义的,但在C ++中则不然。

     

难以转换:语法转换。

     

使用范围广泛:很少。

因此,在C ++ 14中,{strong> long long类型的位字段已签名,并且发布的代码保证按预期工作。