【发布时间】:2026-01-28 18:10:01
【问题描述】:
我最近正在编写一些实际上应该测试其他代码的代码,我偶然发现了一个令人惊讶的整数提升案例。这是最小的测试用例:
#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 节(关于相等/不相等运算符)指出
如果两个操作数都是算术或枚举类型,通常的算术转换是在 两个操作数;如果指定的关系为真,则每个运算符都应返回真,如果是,则返回假 假的。
什么是“通常的算术转换”,它们在标准中的什么地方定义?我的猜测是,对于某些运算符,它们隐含地将较小的整数提升为int 或unsigned int(这也得到了将std::uint8_t 替换为unsigned int 产生0 的事实的支持,并且进一步因为赋值运算符缺少“通常的算术转换”子句)。
【问题讨论】:
-
我不是专家,但我相信对于任何算术运算 (b + 1),短值总是被提升为整数,并且只有在值存储在一个变量。
-
问题已经得到解答,但作为补充,这里正在发生的事情:1) 评估
a+1将a提升为int,因此结果为 256; 2) 赋值a = a + 1强制将值强制转换为uint8_t,通过取值模256 使值介于0 和255 之间; 3) 在a != b+1中,b+1像以前一样被评估为 256,然后a被提升为int,所以你在比较 0 和 256 -
为 C 编写,但在 C++ 中的工作方式相同:Implicit type promotion rules
-
另外,这正是我们不使用 C++1x 的原因:
auto my_u8 = u8a + u8b;。哈,你认为你声明了uint8_t吗?再想想。
标签: c++ language-lawyer integer-promotion