不鼓励使用int类型的位字段吗? C++标准(N33 37):
9.6位字段 4如果值不鼓励使用int类型的位字段吗? C++标准(N33 37):,c++,bit-fields,C++,Bit Fields,9.6位字段 4如果值true或false存储在任何大小的bool类型的位字段中(包括一位位字段),则原始bool值和位字段的值应相等。如果枚举数的值存储在相同枚举类型的位字段中,且位字段中的位数足够大,足以容纳该枚举类型(7.2)的所有值,则原始枚举数值和位字段的值应相等 该标准对其他类型的位字段的任何此类行为都不作承诺。为了理解g++(4.7.3)如何处理其他类型的位字段,我使用了以下测试程序: #include <iostream> enum TestEnum { V1
true
或false
存储在任何大小的bool
类型的位字段中(包括一位位字段),则原始bool
值和位字段的值应相等。如果枚举数的值存储在相同枚举类型的位字段中,且位字段中的位数足够大,足以容纳该枚举类型(7.2)的所有值,则原始枚举数值和位字段的值应相等
该标准对其他类型的位字段的任何此类行为都不作承诺。为了理解g++(4.7.3)如何处理其他类型的位字段,我使用了以下测试程序:
#include <iostream>
enum TestEnum
{
V1 = 0,
V2
};
struct Foo
{
bool d1:1;
TestEnum d2:1;
int d3:1;
unsigned int d4:1;
};
int main()
{
Foo foo;
foo.d1 = true;
foo.d2 = V2;
foo.d3 = 1;
foo.d4 = 1;
std::cout << std::boolalpha;
std::cout << "d1: " << foo.d1 << std::endl;
std::cout << "d2: " << foo.d2 << std::endl;
std::cout << "d3: " << foo.d3 << std::endl;
std::cout << "d4: " << foo.d4 << std::endl;
std::cout << std::endl;
std::cout << (foo.d1 == true) << std::endl;
std::cout << (foo.d2 == V2) << std::endl;
std::cout << (foo.d3 == 1) << std::endl;
std::cout << (foo.d4 == 1) << std::endl;
return 0;
}
#包括
测试枚举
{
V1=0,
V2
};
结构Foo
{
布尔d1:1;
睾丸d2:1;
int d3:1;
无符号整数d4:1;
};
int main()
{
富富,;
foo.d1=真;
foo.d2=V2;
foo.d3=1;
foo.d4=1;
STD:CUT<代码> INT/INGED>是代码>签名< /代码>,在C++中可以使用,所以在第一个代码> INT/INTCOR>字节符号可以被存储。当有2个比特用于<代码>签名INT/CUT>时,它可以等于1, < P>这是完全合乎逻辑的。<代码> INT/COD>是一个带符号整数类型,如果底层架构使用两个补码表示有符号整数(正如所有现代体系结构所做的那样),那么高阶位就是符号位。因此,1位有符号整数位字段可以取值0
或-1
。例如,3位有符号整数位字段可以取值-4
和3
之间的值
没有理由全面禁止有符号整数位字段,只要您了解二的补码表示。是的,类型为int
的位字段是个坏主意,因为它们的符号是由实现定义的。请改用有符号int
或无符号int
对于非位字段声明,类型名int
完全等同于signed int
(或int signed
,或signed
)。对于short
、long
和long
遵循相同的模式:未加修饰的类型名称是有符号版本,您必须添加unsigned
关键字来命名相应的无符号类型
出于历史原因,位字段是一种特殊情况。使用int
类型定义的位字段相当于使用signed int
的同一声明,或使用unsigned int
的同一声明。选择由实现定义(即,它由编译器决定,而不是由程序员决定)。位字段是唯一的上下文,int
和signed int
不(一定)同义。这同样适用于char
、short
、long
和long
引用C++11标准第9.6节[class.bit]:
它是实现定义的,无论是普通的还是显式的
有符号或无符号)字符
,短
,整数
,长
位字段无效
签名或未签名
(我不完全确定这一点的理由。非常旧的C版本没有unsigned
关键字,而且无符号位字段通常比有符号位字段更有用。可能是一些早期的C编译器在引入unsigned
关键字之前实现了位字段。默认情况下,使位字段无符号,即使声明为int
,也可能只是为了方便起见。除了避免破坏旧代码之外,没有真正的理由遵守规则。)
大多数位字段都是无符号的,这当然意味着它们应该这样定义
如果您想要一个有符号位字段(例如,一个4位字段,可以表示非二元补码系统中从-8到+7的值,或者从-7到+7的值),那么您应该显式地将其定义为有符号int
。如果您将其定义为无符号int
,那么一些编译器会将其视为无符号int
如果您不关心位字段是有符号的还是无符号的,那么您可以将其定义为int
——但是如果您定义位字段,那么您几乎肯定会关心它是有符号的还是无符号的。您完全可以使用任何大小不大于无符号int
的位字段有符号的位字段是合法的(至少在宽度大于1的情况下),我个人不喜欢使用它们。但是,如果您确实希望使用有符号位字段,则应显式将其标记为有符号的,因为它依赖于实现,取决于非限定的int
位字段是有符号的还是无符号的。(这类似于char
,但没有显式非限定char*
文本的复杂特性。)
因此,在这种程度上,我同意不鼓励使用int
位字段。[注1]虽然我不知道有哪种实现中,int
位字段是隐式无符号的,但该标准肯定允许它,因此,如果您对符号没有明确的定义,则有很多机会出现特定于实现的意外行为
标准规定有符号整数表示由可选的填充位、恰好一个符号位和值位组成。虽然标准不保证至少有一个值位,--正如OP中的示例所示,gcc
并不坚持有-我认为这是对s的合理解释标准,因为它明确允许
d1: true
d2: 1
d3: -1
d4: 1
true
true
false
true