在C/C++中使用int的位标志实际上是否安全?

Chr*_*vey 14 c c++

我注意到许多C/C++程序员使用以下内容实现了一组标志:

#define FLAG_1 (1 << 0)
#define FLAG_2 (1 << 1)
#define FLAG_3 (1 << 2)

unsigned int my_flags = 0; /* no flag set */
my_flags |= FLAG_2; /* set flag 2 */
Run Code Online (Sandbox Code Playgroud)

但这种方法听起来有效吗?在我看来,它正在假设无符号整数的二进制表示,而不是C/C++语言标准的一部分.例如,"0"实际上是0x0000.

我错了吗?或者我在理论上是正确的,但在目前的标准硬件中没有实践吗?

Jos*_*eld 18

C++

C++ 11标准的重要部分是§3.9.1/ 7(ISO/IEC 14882:2011(E)):

整数类型的表示应使用纯二进制计算系统定义值.

这在脚注中阐明:

49)使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并且乘以2的连续积分幂,除了可能对于具有最高位置的位.(改编自美国国家信息处理系统词典.)

移位运算符的结果是数学定义的.例如,对于E1 << E2:

如果E1具有无符号类型,则结果的值为E1×2 E2,比结果类型中可表示的最大值减少一个模数.否则,如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2 E2,那么这就是结果值; 否则,行为未定义.

按位运算符具体定义为按位.例如,对于按位OR:

执行通常的算术转换; 结果是操作数的按位异或功能.

当然,在as-if规则下,表示并不一定是纯二进制计算系统.编译器必须只生成一个一样的程序.

C

在C99(ISO/IEC 9899:TC3)中,仅对位域和类型对象unsigned char(§6.2.6.1/ 3)保证纯二进制表示法:

存储在无符号位域中的值和unsigned char类型的对象应使用纯二进制表示法表示.

再次在脚注中澄清:

使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并且乘以连续的2的整数幂,除了具有最高位置的位.(改编自美国国家信息处理系统词典.)

该标准特别指出按位运算取决于内部表示(第6.5/4节):

一些运算符(一元运算符〜,以及二元运算符<<,>>,&,^和|,统称为按位运算符)需要具有整数类型的操作数.这些运算符产生的值取决于整数的内部表示,并且具有已签名类型的实现定义和未定义方面.

  • 是的,as-if规则要求保留二进制行为,而不管实际实现如何. (2认同)

Ben*_*igt 12

虽然这是理论上有可能对使用非功率的-2算法,一个体系结构上运行的C或C++的|,&^运营商被定义为具有按位行为,所以这样的机器需要模拟二进制算术.

因此它非常安全和便携.


Jer*_*fin 6

当前的C和C++标准都将无符号整数表示限制为纯二进制表示,因此您拥有的内容完全安全并且保证可以正常工作.

  • @ardentsonata更容易将它们定义为位移,并且没有缺点. (2认同)