为什么 unsigned int 小于零是可能的?

Why is a unsigned int below zero possible?

我只是试图将 unsigned int 降低到 0 以下。令我惊讶的是它有效!

#include<stdio.h>

int main(void)
{
        unsigned int foo = 5;
        foo -= 10;
        printf("%d", foo);
        return 0;
}

编译为

clang -Weverything main.c

这个程序返回

-5

正如 this post 和我个人所知,这是不可能的。但是为什么它会起作用呢?我错过了什么吗?是因为未定义的行为吗?还是 printf?或者别的什么?

printf() 将 foo 的值解释为有符号整数。尝试用 %u 替换 %d。

编辑:正如 dasblinkenlight 所说,这是未定义的行为。编程语言规范没有说明如果发生这种情况应该怎么办,所以它留给了实现。有时这可能会产生不同的结果,但在这种情况下,它可能不会。

此程序使用 printfunsigned int 的值重新解释为有符号整数。虽然当 unsigned int 的值也适合 int 时这不是问题,但这是未定义的行为:

If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined

解释:从五减十 "wraps around",因此根据系统对 unsigned int 的表示,您会得到一个很大的数字。事实证明,这个大数的位表示对应于系统中负五的表示,因此当 printf 将值重新解释为有符号时,将打印负五。

why isn't there any notice from compiler?

有关可能的解释,请参阅 this Q&A

计算机上的数字以二进制补码形式存储。以 2 的补码表示的负数是无符号数范围内的有效数。处理器核心巧妙地实现了 addition/subtractions/multiplication/division,这样它就不需要知道数字的符号来执行这些操作。利用这个核心的C语言将这些数字传递给处理器的运算单元,处理器的运算单元执行请求的操作并得到return结果。这就是您在整数上得到预期结果的原因。