C 运算中的整数提升

Integer promotion in C operation

提问人:Binar Web 提问时间:11/3/2023 最后编辑:Binar Web 更新时间:11/3/2023 访问量:136

问:

uint64_t impulses = 4000000;
uint16_t impulses_per_meter = 999;
uint32_t meters = impulses / impulses_per_meter;

据我了解,在计算操作的最终值之前获得整数提升,然后结果被截断为 。impulses_per_meterimpulses / impulses_per_meteruint16_t

我的理解是正确的还是结果可能不正确?

顺便说一句,我运行它的 MCU 是 8 位。

c 数学 整数

评论

2赞 Weather Vane 11/3/2023
重点是什么?反正结果都是一样的。商为 64 位,并被截断为 32 位。
0赞 Jabberwocky 11/3/2023
这个(长)答案可能会有所帮助
0赞 Weather Vane 11/3/2023
如果处理器不能使用 16 位除数,则必须对其进行提升。
0赞 Jabberwocky 11/3/2023
OT:第三次分配很可能会触发警告,因为 64 位类型正在转换为 32 位类型,并且可能会丢失信息。
1赞 Gerhardh 11/3/2023
“然后结果被截断为uint16_t。”为什么它会被截断为 16 位?您的意思可能是 32 位。正确?

答:

3赞 Blagovest Buyukliev 11/3/2023 #1

标准中有一部分称为“通常的算术转换”。其目的是在算术运算的操作数在类型和符号上不同时确定一种通用类型。

当两个操作数都是整数时(如你所采用的情况),它们都会进行整数提升。升级后,如果两个操作数是相同的类型 (),则这就是表达式的类型。如果它们不同但具有相同的符号,则标准说:int

如果类型具有相同的有符号(有符号或无符号),则其类型具有较低转换等级的操作数将隐式转换为另一种类型。

在您的例子中,这意味着它被隐式转换为(假设数据模型与 相同)。impulses_per_meterunsigned long longuint64_tunsigned long long

但是,将表达式结果 () 分配给 () 涉及截断和数据丢失。现代编译器应发出警告,并且应更改代码。uint64_tmetersuint32_t

3赞 Lundin 11/3/2023 #2

在表达式中:impulses / impulses_per_meter

  • 通常,隐式整数提升是在“通常的算术转换”的第一步(以及大多数其他此类二进制运算符)的两个操作数上执行的。/
  • 在 8 位系统上,为 16 位。 已经是 转换排名相等的类型,因此不需要整数提升。 是类型的,所以那里也没有促销。intimpulses_per_meteruint16_tintimpulsesuint64_t
  • “通常的算术转换”的下一步是转换为与具有最大转换等级的操作数相同的类型,在本例中为 .impulses_per_meter/uint64_t
  • 对类型进行除法,结果是类型。uint64_tuint64_t
  • 在赋值到 期间,除法的结果从 转换为 。如果结果不能放在一个中,您将丢失数据。uint32_tuint64_tuint32_t

有关详细信息,请查看隐式类型升级规则

顺便说一句,在 8 位 MCU 上使用 64 位算术是一个可怕的主意。特别是 64 位除法效率非常低。 适合里面,所以我不确定你在这里做什么。4000000uint32_t