临时操作会导致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 的数为模减少。
为了充分理解这些东西,你需要从隐式类型提升规则开始。许多 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。