C++14 中的有符号位域

Signed bit field in C++14

我相信在 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
}

根据 C++11 标准 §9.6/p3 位域 [class.bit]Emphasis Mine) :

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, or long long bit-field is signed or unsigned. 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 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 ]

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

正如 @T.C. Defect reports referring to the issue were made DR739, DR675 在评论中提到的那样。在 C++14 标准中产生以下分辨率:

措辞 "It is implementation-defined whether a plain (neither explicitly signed nor unsigned) char, short, int, long, or long long bit-field is signed or unsigned." 已被删除,现在的 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 中,普通 int 类型的位字段被签名,并且发布的代码保证按预期工作。