据我所知,我为signed int赋予了一个比它能处理的值更大的值 . 另外,我应该使用 %d
进行签名,将 %u
用于unsigned . 同样,我不应该将 -ve
值赋给unsigned . 但如果我进行这样的分配并使用如下的printf,我会得到如下结果 .
我的理解是,在每种情况下,转换为其两个恭维二进制表示的数量对于 -1
或 4294967295
是相同的 . 这就是为什么 %u
签名打印 4294967295
忽略 -ve
最左边的位 . 当%d用于signed int时,它使用最左边的位作为 -ve
标志并打印 -1
. 类似地, %u
对于无符号打印无符号值但 %d
使其将该数字视为已签名,从而打印 -1
. 那是对的吗?
signed int si = 4294967295;
unsigned int ui = 4294967295;
printf("si = u=%u d=%d\n", si, si);
printf("ui = u=%u d=%d\n", ui, ui);
输出:
si = u=4294967295 d=-1
ui = u=4294967295 d=-1
signed int si = -1;
unsigned int ui = -1;
printf("si = u=%u d=%d\n", si, si);
printf("ui = u=%u d=%d\n", ui, ui);
输出:
si = u=4294967295 d=-1
ui = u=4294967295 d=-1
2 回答
在无符号的情况下,"leftmost"或最高有效位不被忽略,并且不是负数;相反,它的地方 Value 为231 .
在否定的情况下,符号位不是标志;相反,它的位置值为-231 .
在这两种情况下,整数的值等于设置为1的所有二进制数字(位)的位置值的总和 .
以这种方式对带符号值进行编码称为two's complement . 它不是唯一可能的编码;你所描述的被称为符号和数量,例如,一个补充是另一种可能性 . 然而,这些替代编码在实践中很少遇到,尤其是因为两个补码是算术如何在现代硬件上工作,但可能是最神秘的架构 .
这里有一些事情让我们开始说使用
printf
的错误格式说明符是未定义的行为,这意味着程序的结果是不可预测的,实际发生的将取决于许多因素,包括编译器,体系结构,优化级别等等......对于由相应标准定义的有符号/无符号转换,C和C都使其实现定义的行为,以从C草案标准转换大于存储在有符号整数类型中的值:
例如
gcc
选择使用相同的convention as unsigned:当您在C和C中将
-1
分配给无符号值时,结果将始终是该草案C标准中该类型的最大无符号值:C99的措辞更容易理解:
所以我们有以下内容:
结果是
UNSIGNED_MAX
至于
printf
和不正确的格式说明符,我们可以看到草案C99标准部分7.19.6.1
fprintf函数说:对于格式说明符,
fprintf
涵盖printf
,而对于printf
,C则回退到C.