有符号整型类型按位运算的结果是否定义良好?

问题描述:

考虑以下代码:有符号整型类型按位运算的结果是否定义良好?

using integer = int; // or any other fundamental integral type 
using unsigned_integer = typename std::make_unsigned<integer>::type; 
constexpr integer bits = std::numeric_limits<unsigned_integer>::digits; 
integer value = -42; // or any value 
integer mask = static_cast<integer>(1)<<static_cast<integer>(bits-1); 
bool result_and = value & mask; 
bool result_or = value | mask; 
bool result_xor = value^mask; 

我想知道如何以及是根据标准定义这些操作。我是否有保证在所有架构上获得相同的结果?我肯定会对所有体系结构上的符号位进行操作,其符号位为0(正数),1(负数)?

+0

另请参阅[a和b的结果是什么?](http://*.com/q/29394518/1708801),它与密切相关但不重复。 –

在标准中,按位和/或按位或按位异或的结果目前未详细说明,特别是从未定义位。我们有defect report 1857: Additional questions about bits覆盖这个问题,并说:

的位操作的5.11 [expr.bit.and]规范, 5.12 [expr.xor]和5.13 [expr.or]使用未定义在描述操作时使用术语“按位”,而不指定是否为 值或视图中的对象表示。这种分辨率的

某些部分可能被定义的“位”(其否则目前用C未定义++)作为2.

给定的功率的值和分辨率为:

CWG决定重新描述操作 本身,以避免引用位,将较大的定义“位”等的问题分割为考虑进一步考虑的问题1943。

这导致合并defect report 1943: Unspecified meaning of “bit”

左移符号类型的结果将取决于底层表示。

5.8目前的措辞[expr.shift]第2款使得未定义行为 创建most-:我们可以从做它明确定义向左转移到符号位并表示defect report 1457: Undefined behavior in left-shift看到这

:由 左移位(签字)1到符号位,尽管这不是 罕见完成,正确适用于大多数 (二进制补码)的架构给定类型的负整数

...如果E1有签名类型和非负数VA lue,并且E1⨯2E2可以在结果类型中表示,那么这就是结果值; 否则,行为是不确定的。

因此,此技术不能用于常量表达式, 将破坏大量的代码。

地注意到对大多数的 (二进制补码)架构正常工作的,声明的重点。所以它依赖于例如二进制补码的基本表示。

关于左和右移位运算符,从C++标准第5.8节:

的行为是不确定如果将右操作数是负的,或大于 或等于所述长度在受促进的左侧的位操作数。

然后它说,向左移位运算符E1 < < E2导致一个未定义的行为当所有满足以下条件:

  • 左操作数有符号的类型。
  • 左操作数有一个负值,或者它有一个非负值,使E1×2^E2在结果类型中不可表示。

关于右移运算符E1 >> E2,如果左操作数具有带符号类型和负值,则行为与实现有关。

按位AND,XOR和OR运算符对所有积分类型都定义良好。这分别在第5.11,5.12和5.13节中规定。

但是,请注意,有符号整数值的表示可以是二进制补码,一进制补码或有符号幅度。尽管大多数编译器使用二进制补码表示法。这些包括gcc,VC++,icl和Clang。

运营商&|^是按位,并处理各个位,所以他们会做你写什么:应用mask

左移<<操作符有点棘手。如果您改变负值或者将1移至符号位位置或超出位置,它将导致未定义的行为。

static_cast<integer>(1)<<static_cast<integer>(bits-1);

看来你转移1那里签位的位置,它是不确定的行为。