在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 }
解决方法
A bit-field shall not be a static member. A bit-field shall have
integral or enumeration type (3.9.1). It is implementation-defined
whether a plain (neither explicitly signed nor unsigned)char
,short
,
int
,long
,orlong long
bit-field is signed or unsigned. Abool
value
can successfully be stored in a bit-field of any nonzero size. The
address-of operator & shall not be applied to a bit-field,so there
are no pointers to bitfields. A non-const reference shall not be bound
to a bit-field (8.5.3). [ Note: If the initializer for a reference of
type const T& is an lvalue that refers to a bit-field,the reference
is bound to a temporary initialized to hold the value of the
bit-field; the reference is not bound to the bit-field directly. See
8.5.3. —end note ]
所以你对第一部分是正确的.实际上,声明为signed的结构的位字段仍然被解释为有符号或无符号,解释是实现定义的.
正如@T.C年的评论中已经提到的那样.提到该问题的缺陷报告是在DR739,DR675进行的.导致C 14标准中的以下决议:
措辞“它是实现定义的是一个普通(既没有显式签名也没有未签名)char,short,int,long或long long位字段是有符号还是无符号.”,已被删除,C 14措辞现在是:
A bit-field shall not be a static member. A bit-field shall have
integral or enumeration type (3.9.1). A bool value can successfully be
stored in a bit-field of any nonzero size. The address-of operator &
shall not be applied to a bit-field,so there are no pointers to
bit-fields. A non-const reference shall not be bound to a bit-field
(8.5.3). [ Note: If the initializer for a reference of type const T&
is an lvalue that refers to a bit-field,the reference is bound to a
temporary initialized to hold the value of the bit-field; the
reference is not bound to the bit-field directly. See 8.5.3. —end note
]
同样在§C.1.8第9章:类[diff.class]中添加了以下部分:
9.6
Change: Bit-fields of type plain int are signed.
Rationale: Leaving the choice of signedness to implementations could lead to inconsistent definitions of
template specializations. For consistency,the implementation freedom was eliminated for non-dependent
types,too.Effect on original feature: The choice is implementation-defined in C,but not so in C++.
Difficulty of converting: Syntactic transformation.
How widely used: Seldom.
因此,在C 14中,对plain int类型的位字段进行了签名,并且保证发布的代码按预期工作.