位移运算符的结果类型是什么?

22
考虑以下代码清单:
#include <type_traits>
#include <cstdint>

static_assert(std::is_same_v<decltype(31), int32_t>);
static_assert(std::is_same_v<decltype(31u), uint32_t>);

static_assert(std::is_same_v<decltype((signed char)1 << 1), int32_t>);
static_assert(std::is_same_v<decltype((signed char)1 << 1u), int32_t>);
static_assert(std::is_same_v<decltype((unsigned char)1 << 1), int32_t>);
// Signed result for unsigned char
static_assert(std::is_same_v<decltype((unsigned char)1 << 1u), int32_t>);
// But unsigned for uint32_t
static_assert(std::is_same_v<decltype(1u << 1u), uint32_t>);

使用GCC和Clang编译都很好。但是我对operator<<(uint8_t, uint32_t)感到困惑,为什么结果是有符号的?

2个回答

28

每个[expr.shift]

操作数必须是整数或未作用域枚举类型,将执行整数提升。 结果的类型是提升后左操作数的类型。[...]

因此对于unsigned charint,左操作数从unsigned char提升为int1(请参见[conv.prom]),结果类型是提升后左操作数的类型,即int


1 至少在大多数常见平台上(其中sizeof(char) < sizeof(int)),否则如果sizeof(char) == sizeof(int),它可能会被提升为unsigned int


14

对于 << 运算符,左操作数使用整形提升进行提升。整形提升有一些技术细节,但主要包括:比 int 窄的类型会被提升为int,其他整数类型保持不变。

<< 运算符的结果类型是其左操作数经过提升后的类型。

在您的示例中,(signed char)1(unsigned char)1int 窄,因此它们会被提升为 int,相当于您的 C++ 实现中的 int32_t31 是一个 int,因此它保持不变。 31u1uunsigned int,因此它们保持为 unsigned int


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接