【发布时间】:2020-10-30 10:58:39
【问题描述】:
uint32_t 和 uint64_t 的结果是预期的,但 uint8_t 和 uint16_t 的促销活动很奇怪。在 c++14/c++17、gcc 和 clang、64 位 linux 上测试,sizeof(int) == 4。
#include <cstdint>
using namespace std;
static_assert( uint8_t(-1)*uint8_t(-1) == 0xfe01); // OK, but why not 1?
static_assert( uint8_t(-1)*uint8_t(-1) == 1); // error: static assertion failed
static_assert( uint16_t(-1)*uint16_t(-1) == 1); // error: static_assert expression is not an integral constant expression
static_assert( uint32_t(-1)*uint32_t(-1) == 1); // OK
static_assert( uint64_t(-1)*uint64_t(-1) == 1); // OK
以下情况下std::uint16_t是否提升为int?
static_assert( uint16_t(-1)*uint16_t(-1) == uint16_t(uint16_t(-1)*uint16_t(-1)));
编译器消息是:
error: static_assert expression is not an integral constant expression
static_assert( uint16_t(-1)*uint16_t(-1) == uint16_t(uint16_t(-1)*uint16_t(-1)));
note: value 4294836225 is outside the range of representable values of type 'int'
static_assert( uint16_t(-1)*uint16_t(-1) == uint16_t(uint16_t(-1)*uint16_t(-1)));
更有趣的是,std::uint8_t 的相同断言是正确的,但 失败:
static_assert( uint8_t(-1)*uint8_t(-1) == uint8_t(uint8_t(-1)*uint8_t(-1))); //error: static_assert failed
static_assert( uint8_t(-1)*uint8_t(-1) == 0xfe01); // does not fail
所以看起来uint8_t 被提升为uint16_t,但uint16_t 被提升为已签名 int。 uint32_t 未被提升 uint64_t。
任何人都可以告诉我为什么要进行这些促销,是在标准中指定的,还是在不同的实现中可能有所不同?
【问题讨论】:
-
将
-1转换为任何无符号整数类型会给出该类型可以表示的最大值。无法以无符号类型表示值-1。
标签: c++ unsigned integer-promotion