C++14 中的有符号位域
Signed bit field in C++14
我相信在 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
}
根据 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
的结构的位字段仍然被解释为 signed
或 unsigned
,解释是实现定义的。
正如 @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
类型的位字段被签名,并且发布的代码保证按预期工作。
我相信在 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
}
根据 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
, 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 ]
所以你对第一部分是正确的。事实上,在 C++14 之前,声明为 signed
的结构的位字段仍然被解释为 signed
或 unsigned
,解释是实现定义的。
正如 @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
类型的位字段被签名,并且发布的代码保证按预期工作。