如何解决无符号整数会提升为有符号吗?表达式的类型是什么uint16_t-1 *uint16_t-1
对于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
被提升为 signed int
。 uint32_t
未被提升为uint64_t
。
任何人都可以告诉我为什么要进行这些促销活动,它是在标准中指定的,还是在不同的实现上可能有所不同?
解决方法
看起来
uint8_t
被提升为uint16_t
,但是uint16_t
被提升为signed int。uint32_t
未被提升为uint64_t
。
不,那是不正确的。仅将比int窄的类型提升为int,因此,如果int的位数超过16位,则uint8_t
和uint16_t
都将提升为int。
对于uint8_t(-1)*uint8_t(-1)
,它等效于0xFF*0xFF
,结果将为0xFE01
OTOH uint16_t(-1)*uint16_t(-1)
与0xFFFF*0xFFFF
相同,结果为0xFFFE0001 = 4294836225,并且超出int的范围。和签名溢出是未定义的行为
无符号整数会提升为有符号吗?
取决于操作数的大小与int
的大小有关。但是,是的,这很典型。
static_assert( uint8_t(-1)*uint8_t(-1) == 0xfe01); // OK,but why not 1?
它不是1,因为uint8_t(-1)
是255,而255 * 255是65025。在具有32位int的系统上,该值在可表示的值之内。
所以看起来uint8_t被提升为uint16_t
不。提升总是发生在int
或更高等级的整数上。在uint8_t
为16位的系统上,int
可以提升为16位类型,但是由于uint8_t
的所有值都可以用带符号的int
表示,因此将是结果促销活动。
在不同的实现上可以有所不同吗?
在不同的语言实现中,可表示值的范围有所不同,这会影响升级后的类型。
是否在标准中指定
是的
您知道如何抑制升迁为带符号的int并将其提升为无符号的int吗?
否,无法更改促销。但是您可以将值显式转换为所需的类型,以便不进行升级。
,算术运算符不接受小于int
的类型作为参数。
对于较小的参数,将积分提升为int
。
这是结果不一致的原因:
- 当乘以小于
int
的类型时,您将获得晋升, - 当乘以更大的类型时,您不会(如果它们相同)。
确切的规则太复杂了,无法总结而不会出错,但是在那些CppReference文章中对此进行了描述:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。