对于上下文,我正在使用
g++ -std=gnu++23 -O3 -Wall
来编译我的代码(如果有什么区别的话)。我使用的是 64 位小端系统。
以下代码片段都显示了一些看似病态的行为:警告“左移计数>=类型宽度”的出现时间比我预期的要晚(部分解释见here),但似乎并没有像我那样进行完整的整数提升都会期望。
#include <cstdint>
#include <iostream>
int main()
{
// any value will cause the confusing behaviour, of course
uint8_t a = 5;
a <<= 7;
// 128, as expected
std::cout << static_cast<int>(a) << '\n';
uint8_t b = 5;
b <<= 8;
// 0, as expected, if slightly dubious (8 = width of type, right?)
std::cout << static_cast<int>(b) << '\n';
uint8_t c = 5;
c <<= 16;
// 0, as expected, assuming a promotion to a larger unsigned int type
std::cout << static_cast<int>(c) << '\n';
uint8_t d = 5;
d <<= 31;
// 0, as expected, assuming a promotion to a larger unsigned int type
std::cout << static_cast<int>(d) << '\n';
uint8_t e = 5;
e <<= 64;
/*
raises a warning, rather understandably
(I suppose it isn't aware of __uint128_t?)
*/
// still outputs 0, although I assume this is undefined behaviour
std::cout << static_cast<int>(e) << '\n';
uint8_t f = 5;
f <<= 32;
/*
raises a warning for some reason
(shouldn't it just promote to uint64_t?)
*/
// still outputs 0, although I assume this is undefined behaviour
std::cout << static_cast<int>(f) << '\n';
}
发生什么事了?
为什么“左移计数> =类型宽度”似乎很晚才开始?
我想它不知道 __uint128_t?
__uint128_t
是编译器扩展。扩展不是标准整数促销的一部分。
不应该升级为uint64_t吗?
没有。
整数促销的规则是 https://en.cppreference.com/w/c/language/conversion#Integer_promotions 。这是,强调我的::
整数提升是对 rank 小于或等于 int 的rank 的任何整数类型值或 _Bool(until C23)bool(since C23)、int、signed int、unsigned 类型的位字段的隐式转换int,为 int 或 unsigned int 类型的值。
假设正常系统,
uint8_t
为unsigned char
。晋升为unsigned int
。您系统上的 unsigned int
宽度为 32 位。