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

时间:2012-10-02 18:19:04

标签: 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 */

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

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

4 个答案:

答案 0 :(得分:18)

C ++

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

  

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

这在脚注中阐明:

  

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

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

  

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

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

  

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

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

C

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

  

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

再次在脚注中澄清:

  

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

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

  

一些运算符(一元运算符〜,二元运算符&lt;&lt;,&gt;&gt;,&amp;,^和|,   统称为位运算符)需要具有的操作数   整数类型。这些运算符产生的值取决于内部表示   整数,并为签名类型提供实现定义和未定义的方面。

答案 1 :(得分:12)

虽然理论上可以在使用非幂2算法的体系结构上运行C或C ++,但|&^运算符被定义为具有按位行为,因此这样的机器需要模拟二进制算术。

因此它非常安全和便携。

答案 2 :(得分:6)

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

答案 3 :(得分:1)

向右移位总是减小整数的值,而向左移位将始终增加该值。这与机器的字节顺序无关,所以要回答你的问题:“是的,这是合理的,因为无论系统的字节顺序如何,位移都是一样的”

这会回答你的问题吗?