分配给较大宽度整数时的 C 整数溢出行为

发布于 2024-07-17 04:22:09 字数 267 浏览 9 评论 0原文

如果我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

叹沉浮 2024-07-24 04:22:09

这个问题其实有些复杂。 算术表达式的操作数使用特定规则进行转换,您可以在 的第 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 than int, say short int, then the operands are converted to int and you get -4000, but on a 16-bit system, uint16_t could be unsigned int and conversion to a signed type would not happen automatically.

东京女 2024-07-24 04:22:09

简短的答案是,在减法过程中,这些都被提升为 int。 对于长答案,请查看 C 标准,其中讨论了算术表达式中的整数提升。 标准中的相关语言:

如果一个int可以代表所有的值
原始类型,值为
转换为 int; 否则,就是
转换为无符号整数。 这些
称为整数促销
所有其他类型均未改变
整数促销。

细节也在那里,但它们变得非常令人讨厌。

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:

If an int can represent all values of
the original type, the value is
converted to an int; otherwise, it is
converted to an unsigned int. These
are called the integer promotions.
All other types are unchanged by the
integer promotions.

The details are in there, too, but they get pretty nasty.

×眷恋的温暖 2024-07-24 04:22:09

在减法过程中,两个操作数都提升为 int32_t。 如果结果大于 int32_t 的最大值,您就会看到溢出。

Both operands are promoted to int32_t during the subtraction. If the result had been larger than the maximum value for int32_t you would've seen overflow.

花辞树 2024-07-24 04:22:09

事实上,存在溢出,但 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文