位操作的标准(跨平台)方法

Standard (cross-platform) way for bit manipulation

本文关键字:方法 跨平台 标准 位操作      更新时间:2023-10-16

是数字的不同二进制表示形式(例如,取大/小端序),这是跨平台的:

// NOTE: FIXED-SIZE unsigned integral type
some_unsigned_type variable = some_number;
// set n-th bit, starting from 1,
// right-to-left (least significant-to most significant)
variable |= ( 1 << ( n - 1 ) );
// clear the same bit:    
variable &= ~( 1 << ( n - 1 ) );

换句话说,编译器是否始终负责固定大小的无符号数字的不同二进制表示形式,或者它是特定于平台的?

如果variable是有符号整型(例如,int)并且其值为

  • 阳性
  • 阴性?

《标准》对此有何规定?

附言而且,是的,我对两者都很有趣 -CC++,请不要告诉我它们是不同的语言,因为我知道这个:)

如果需要,我可以粘贴真实示例,但帖子会变得太长

除非some_unsigned_type是固定宽度的类型,否则这是您的第一个特定于平台的类型。在一个平台上,您可能会转移一些值本身永远不会重复的信息,而在另一个平台上,它可能不会。例:

16 bit 'int':
1000 0000  0000 0000
<<1 = 0000 0000  0000 0000
>>1 = 0000 0000  0000 0000
32 bit 'int':
0000 0000  0000 0000   1000 0000  0000 0000
<<1 = 0000 0000  0000 0001   0000 0000  0000 0000
>>1 = 0000 0000  0000 0000   1000 0000  0000 0000

C++标准中的5.8 Shift Operators也这样说:

行为未定义,如果正确的操作数 为负数,或大于或等于提升的左操作数的长度(以位为单位)。

因此,如果将整数移动的位数多于实际位数,则会进入未定义的行为。 例如,如果将short值左移 17 位,它可能会在某些机器上为您提供 UB,但不是全部。

C11在6.5.7 Bitwise shift operators中说,除了其他事情之外,这个:

E1 >> E2的结果是E1位位置右移E2。如果E1具有无符号类型 或者,如果E1具有有符号类型和非负值,则结果的值为整数E1 / 2E2商的一部分。如果E1具有有符号类型和负值,则 结果值由实现定义。

因此,符号数字移位是不便携的。

因此,整数的一般答案是:

对整数的按位操作不可移植。

免责声明:我隐含地假设您正在谈论具有固定宽度的整数类型。否则移位是非常危险的...

标准: n3337 C++11

移位的定义对于无符号类型或有符号类型 (*) 中的正值是数学定义的,因此不受基础硬件表示形式的影响。

5.8 移位运算符

2E1 << E2的值E1E2位位置左移;空出的位填充为零。如果E1具有无符号类型,则结果的值为E1 × 2E2,比结果类型中可表示的最大值多减模 1。否则,如果E1具有有符号类型和非负值,并且E1×2E2在结果类型中可表示,则这就是结果值;否则,行为是未定义的。

3E1 >> E2的值E1E2位位置右移。如果E1具有无符号类型,或者E1具有有符号类型和非负值,则结果的值是E1/2E2商的整数部分。如果E1具有带符号类型和负值,则结果值由实现定义。

出于同样的原因,我认为按位andornegate是可以的:它们是用数学定义的。

5.3.1 一元运算符 [expr.unary.op]

10˜的操作数应具有整备或无作用域枚举类型;结果是其操作数的 one 补码。

5.11 按位 AND 运算符 [expr.bit.and]

1执行通常的算术转换;结果是操作数的按位 AND 函数。运算符仅适用于整型或无作用域枚举操作数。

5.13 按位包含 OR 运算符 [expr.or]

1执行通常的算术转换;结果是其操作数的按位包含 OR 函数。运算符仅适用于整型或无作用域枚举操作数。

然而,我承认我对后两者不太确定,我找不到按位XX函数的任何定义,所以即使我相信他们指的是数学对应物,我也不能保证。

(*) 感谢 phresnel 指出这一点。

如果您移动负数(或有符号)数字(通过大多数实现是相同的 U2 事物),它是特定于实现的。如果您将无符号数字移位的值不超过变量中的位数,则大多数用途都是可移植的。