来自无类型语言(PHP)我对C中的数据类型感到有点困惑。我面临以下奇怪的行为。
//First case
unsigned int a;
a = -1;
printf("a = %u", a); //Outputs a strange number, no problem here
//Second case
unsigned int a;
a = -1;
printf("a = %d", a); //Outputs -1
我不明白的是a
“在我们明确说出unsigned
之后如何”包含“已签名的值?
如何只在第二种情况下格式化输出呢?
答案 0 :(得分:4)
正如其他人已经说过的那样,你必须始终牢记价值与其表现形式之间的差异,因为在C中这两个概念是分开的。
通过赋值,您可以将值放入特定的内存区域;使用printf()和类似的,你试着解释这样的值。
为了澄清,请尝试理解这一点:
#include <stdio.h>
int main() {
int val = 2181448;;
printf("%s\n", ((char*)&val)); // * Outputs: "HI!"
return 0;
}
这将打印“HI!”因为你把这个赋值放在一个连续的内存区域('int'这里至少有4个字节宽)数字“2181448”,十六进制是0x00214948,即:
如果你让printf把它解释为一个字符串(请注意,转换只是为了避免编译器警告)(*由于反向字节)你会看到输出这样的数字作为一个4长字符串零终止'H''我''!' '\ 0'
答案 1 :(得分:2)
-1
将表示为10000000 00000000 00000000 00000001
(如果int
有4个字节,就像我的情况一样)。当您使用%d
输出时,printf()
会将其解释为 normal int ,因此它会将前导1
解释为符号,并打印{{ 1}}。如果您将其输出为-1
,则%u
知道它是未签名的,并将前导printf()
解释为1
,从而导致2^32
作为输出。
答案 2 :(得分:2)
因为那是printf
的作用。它不知道提供的值的类型。因此,它将在a
中找到它并将其解释为有符号整数,因为您通过给它%d
告诉它这样做。
printf
也会非常危险。你的程序会在没有任何消息的情况下崩溃。
答案 3 :(得分:2)
编译器会将-1转换为系统的正确签名数字格式,在99.9%的情况下,这将是2的补码。在具有32位整数的二进制补码系统中,-1将对应于0xFFFFFFFF。但是如果你将它存储在一个无符号变量中,你将获得42.9亿的价值。
然后,您尝试使用%d格式说明符打印42.9亿,这是为负数保留的。然后程序再次将0xFFFFFFFF解释为-1。
总结一下,在二进制级别上没有负数。根据您选择显示二进制文件的方式,您可以形成负数。尽管如此,它只是1和0:你不能在计算机存储单元中保存减号。