临时操作会导致 8 位嵌入式系统溢出吗?

问题描述

在下面的示例中,“a + b”将溢出两个变量的大小。这个临时结果会存储在 16 位空间还是需要的最大空间?

这种情况是否跨编译器标准化? 系统架构重要吗?我在 8 位微控制器上。 Short 类型为 16 位。

res 是否等于 50000、17232 或未定义?

unsigned short a = 50000;
unsigned short b = 50000;
unsigned short res = 0;

void main()
{
    res = (a + b) / 2;
}

解决方法

严格来说,无符号类型不会溢出而是“环绕”,这是定义明确的行为,但可能出乎意料。正式参见例如 C 标准 C17 6.2.4/9:

涉及无符号操作数的计算永远不会溢出, 因为无法由结果无符号整数类型表示的结果是 以比可以得到的最大值大 1 的数为模减少 由结果类型表示。

为了完全理解这些内容,您需要从 Implicit type promotion rules 开始。许多 C 表达式中都有各种隐含和微妙的东西。

在这种特殊情况下,不可能有任何隐式转换,因为 unsigned short 在任何已知的 8 位系统上都是 16 位,int 也是如此。在这种情况下,unsigned short 只是转换为 unsigned int,两者都是 16 位。

由于它是一个无符号类型,C 标准保证环绕并产生值 34464,这意味着最终结果保证在所有 8- 和 16- 上变为 17232现实世界中的位系统。如果类型已签名,则不会有任何保证,但会因为溢出而出现未定义的行为。


总结:

这个临时结果会存储在 16 位空间还是需要的最大空间?

16 位空间,因为只有(可能提升的)操作数的类型才重要。

这种情况是否跨编译器标准化?

是的,在无符号类型的情况下,代码在 8 位和 16 位系统上是 100% 可移植的。这是由 C 标准保证的。

系统架构重要吗?

是的,int 的大小在决定是否推广某物时很重要。在 8 位和 16 位苦味中,int 始终是事实上的 16 位(尽管理论上 C 允许它是其他东西)。在 32 位和 64 位苦味中,它实际上始终是 32 位。

res 是否等于 50000、17232 或未定义?

8 位和 16 位系统上为 17232,32 位和 64 位系统上为 50000。