我相信在C ++ 14之前,声明为int
的结构的位字段仍被解释为signed
或unsigned
,解释是实现定义的。参考: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
}
答案 0 :(得分:5)
根据C ++ 11标准§9.6/ p3比特字段[class.bit] ( Emphasis Mine ):
位字段不应是静态成员。位域应具有 积分或枚举类型(3.9.1)。 它是实现定义的 是否是明文(既未明确签名也未签名)
char
,short
,int
,long
或long long
位字段已签名或未签名。bool
值 可以成功地存储在任何非零大小的位字段中。该 运营商地址&amp;不应该应用于位域,所以那里 没有指向位域的指针。非const引用不受约束 到一个位域(8.5.3)。 [注意:如果初始化器为参考 类型const T&amp;是一个左值,引用一个位字段,即引用 绑定到临时初始化以保存的值 位字段;引用不直接绑定到位字段。看到 8.5.3。 - 后注]
所以你对第一部分是正确的。确实,直到C ++ 14,声明为signed
的结构的位字段仍然被解释为signed
或unsigned
,解释是实现定义的。
正如@T.C在本评论中已经提到的那样。提及该问题的缺陷报告DR739,DR675。导致C ++ 14标准中的以下解决方案:
措辞“它是实现定义的是普通(既未明确签名也未签名)char
,short
,int
,long
或{{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
类型的位字段已签名,并且发布的代码保证按预期工作。