为什么 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 所说,这是未定义的行为。编程语言规范没有说明如果发生这种情况应该怎么办,所以它留给了实现。有时这可能会产生不同的结果,但在这种情况下,它可能不会。
此程序使用 printf
将 unsigned 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结果。这就是您在整数上得到预期结果的原因。
我只是试图将 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 所说,这是未定义的行为。编程语言规范没有说明如果发生这种情况应该怎么办,所以它留给了实现。有时这可能会产生不同的结果,但在这种情况下,它可能不会。
此程序使用 printf
将 unsigned 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结果。这就是您在整数上得到预期结果的原因。