首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++意外整数提升

C++意外整数提升
EN

Stack Overflow用户
提问于 2019-05-10 00:43:10
回答 1查看 715关注 0票数 7

我最近写了一些代码,实际上是用来测试其他代码的,我偶然发现了一个令人惊讶的整数提升的例子。下面是最小的测试案例:

代码语言:javascript
运行
复制
#include <cstdint>
#include <limits>

int main()
{
    std::uint8_t a, b;
    a = std::numeric_limits<std::uint8_t>::max();
    b = a;

    a = a + 1;

    if (a != b + 1)
        return 1;
    else
        return 0;
}

令人惊讶的是,这个程序返回1。一些调试和预感显示,条件中的b + 1实际上返回了256,而赋值中的a + 1产生了预期值0。

C++17草案第8.10.6节(关于平等/不可转让运算符)规定:

如果两个操作数都是算术或枚举类型的,则对两个操作数执行通常的算术转换;如果指定的关系为真,则每个操作符应生成true;如果指定的关系为false,则为false。

什么是“通常的算术转换”,它们在标准中的定义是什么?我的猜测是,对于某些运算符,它们隐式地将较小的整数推广到intunsigned int (这也得到了以下事实的支持:用unsigned int替换std::uint8_t会产生0,而且赋值运算符没有“通常的算术转换”子句)。

EN

回答 1

Stack Overflow用户

发布于 2019-05-10 01:01:52

你的猜测是正确的。C++中许多运算符(例如二进制运算和比较运算)的操作数受通常的算术转换的限制。在C++17中,通常的算术转换是在[expr]/11中指定的。我不想引用整个段落,因为它很大(你只需点击链接),但是对于积分类型,通常的算术转换归结为积分提升,然后有效地进行一些推广,如果初始积分提升后两个操作数的类型不一样,那么较小的类型就会转换为两者中较大的一个。积分提升基本上意味着任何小于int的类型都将被提升为intunsigned int,这两个类型中的任何一个都可以表示原始类型的所有可能值,这主要是导致示例中的行为的原因。

正如您自己已经知道的,在您的代码中,通常的算术转换发生在a = a + 1;中,最明显的是,在您的if条件下。

代码语言:javascript
运行
复制
if (a != b + 1)
    …

其中,b被提升为int,使得b + 1的结果为int类型,而a被提升为int!=,因此发生在int类型的值上,从而导致条件为真而不是假…。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56069291

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档