c++ - 为什么当左侧操作数为负值时,左移操作会调用未定义行为?

标签 c++ c language-lawyer undefined-behavior bit-shift

在 C 中,当左侧操作数为负值时,按位左移操作调用未定义行为。

来自 ISO C99 (6.5.7/4) 的相关引用

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

但在 C++ 中,行为是明确定义的。

ISO C++-03 (5.8/2)

The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 multiplied by the quantity 2 raised to the power E2, reduced modulo ULONG_MAX+1 if E1 has type unsigned long, UINT_MAX+1 otherwise. [Note: the constants ULONG_MAXand UINT_MAXare defined in the header ). ]

意思是

int a = -1, b=2, c;
c= a << b ;

在 C 中调用未定义行为,但该行为在 C++ 中已明确定义。

是什么迫使 ISO C++ 委员会认为这种行为与 C 中的行为相反?

另一方面,当左操作数为负时,行为是实现定义按位右移操作,对吧?

我的问题是为什么左移操作调用 C 中的未定义行为,为什么右移操作符只调用实现定义的行为?

P.S:请不要给出“这是未定义的行为,因为标准是这样说的”这样的答案。 :P

最佳答案

您复制的段落是关于无符号类型的。行为在 C++ 中未定义。来自上一个 C++0x 草案:

The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

编辑:看看 C++98 论文。它根本没有提到签名类型。所以它仍然是未定义的行为。

右移负数是实现定义的,对。为什么?在我看来:实现定义很容易,因为左边的问题没有截断。当您向左移动时,您不仅必须说出从右侧移动的内容,还必须说出其余位发生的情况,例如用二进制补码表示,这是另一回事。

关于c++ - 为什么当左侧操作数为负值时,左移操作会调用未定义行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3784996/

相关文章:

c - 为什么来自 C 标准工作组的文档受密码保护?

c - 创建后我怎么能记住树的根

c - 在 C 中使用空终止字符作为空指针

c++ - 使用function-try-block时在Visual Studio中发出C4297警告(假定函数不会引发异常,但会引发异常)

c++ - 从 float 中提取单个数字

c - 从 32 位应用程序中查找 64 位进程的模块名称

c++ - C++ 标准的哪一部分阻止显式指定此模板的参数?

c++ - 将 libxbee 与 MinGw 和 eclipse 结合使用

c++ - Unresolved bind 和 make_pair 过载

c++ - 来自 std::vector<std::uint32_t> 保存数组中原始 RGB 值的 CBitmap