分配给较大宽度整数时的 C 整数溢出行为
如果我在 C 中执行以下代码:
#include <stdint.h>
uint16_t a = 4000;
uint16_t b = 8000;
int32_t c = a - b;
printf("%d", c);
它会正确打印“-4000”作为结果。 但是,我有点困惑:从另一个整数中减去一个更大的无符号整数时,不应该出现算术溢出吗? 这里有什么选角规则在起作用? 这个问题似乎有点菜鸟,所以任何参考资料将不胜感激。
If I execute the following code in C:
#include <stdint.h>
uint16_t a = 4000;
uint16_t b = 8000;
int32_t c = a - b;
printf("%d", c);
It correctly prints '-4000' as the result. However, I'm a little confused: shouldn't there be an arithmetic overflow when subtracting a larger unsigned integer from the other? What casting rules are at play here? This question seems a bit noobish, so any references would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这个问题其实有些复杂。 算术表达式的操作数使用特定规则进行转换,您可以在 的第 3.2.1.5 节中看到这些规则标准(C89)。 对于您的情况,答案取决于
uint16_t
的类型。 如果它小于int
,例如short int
,则操作数将转换为int
并且您得到 -4000,但在 16-位系统,uint16_t
可能是unsigned int
并且不会自动转换为有符号类型。The issue is actually somewhat complicated. Operands of arithmetic expressions are converted using specific rules that you can see in Section 3.2.1.5 of the Standard (C89). In your case, the answer depends on what the type
uint16_t
is. If it is smaller thanint
, sayshort int
, then the operands are converted toint
and you get -4000, but on a 16-bit system,uint16_t
could beunsigned int
and conversion to a signed type would not happen automatically.简短的答案是,在减法过程中,这些都被提升为
int
。 对于长答案,请查看 C 标准,其中讨论了算术表达式中的整数提升。 标准中的相关语言:细节也在那里,但它们变得非常令人讨厌。
The short answer is that these are all promoted to
int
during the subtraction. For the long answer, look at section 6.3.1.1 of the C standard, where it talks about integer promotions in arithmetic expressions. Relevant language from the standard:The details are in there, too, but they get pretty nasty.
在减法过程中,两个操作数都提升为
int32_t
。 如果结果大于int32_t
的最大值,您就会看到溢出。Both operands are promoted to
int32_t
during the subtraction. If the result had been larger than the maximum value forint32_t
you would've seen overflow.事实上,存在溢出,但 C 没有告诉你。
当解释为有符号整数时,溢出留下的值恰好为 -4000。 这按照 2 的补码机器上的设计工作。
尝试将结果解释为无符号,您会注意到,当 u1 < > 时,(u1-u2) 的计算结果为一些看似不相关的数字。 u2。
There is, in fact, an overflow but C does not tell you.
The overflow leaves a value that happens to be -4000 when interpreted as a signed integer. This works as designed on 2's complement machines.
Try to interpret the result as unsigned, and you'll notice that (u1-u2) evaluates to some seemingly unrelated number when u1 < u2.