Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无符号整数存储有符号值_C - Fatal编程技术网

C 无符号整数存储有符号值

C 无符号整数存储有符号值,c,C,来自一种无类型语言(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 我不明白的是,一个“包含”一个有符号的值,而我们明确地说它是无符号的

来自一种无类型语言(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
我不明白的是,
一个
“包含”一个有符号的值,而我们明确地说它是
无符号的


仅在第二种情况下格式化输出如何才能做到这一点?

-1
表示为类似
1000000000000000000000000000001
(如果
int
与我的情况一样有4个字节)。当您使用
%d
输出它时,
printf()
将其解释为正常整数,因此它将前导的
1
解释为符号,并打印
-1
。如果您将其输出为
%u
printf()
知道它是无符号的,并将前导的
1
解释为
2^32
,从而将
4294967295
作为输出。

-1将表示为
1000000000000000000000000000001
(如果
int
与我的情况一样有4个字节)。当您使用
%d
输出它时,
printf()
将其解释为正常的int,因此它将前导的
1
解释为符号,并打印
-1
。如果您将其输出为
%u
printf()
知道它是无符号的,并将前导的
1
解释为
2^32
,从而将
4294967295
作为输出。

因为这就是
printf
所做的。它不知道提供的值的类型。因此它会将在
a
中找到的数据解释为有符号整数,因为它可以通过给它
%d
来执行此操作


printf
如果您为格式化代码输入了不正确的值,或者完全忽略了它们,也会非常危险。您的程序将在没有任何消息的情况下崩溃。

因为这就是
printf
所做的。它不知道提供的值的类型。因此它将获取在
a
中找到的数据并对其进行解释作为有符号整数,因为您通过给它
%d
来告诉它这样做


printf
如果您为格式化代码输入了不正确的值,或者完全忽略了它们,也会非常危险。您的程序将在没有任何消息的情况下崩溃。

编译器会将-1转换为您系统的正确有符号数字格式,在99.9%的情况下,这将是二的补码。在二的补码系统上对于32位整数,-1将对应于0xFFFFFFFF。但如果将其存储在无符号变量中,将得到值42.9亿

然后尝试使用%d格式说明符打印42.9亿,该说明符保留为负数。然后程序再次将0xFFFFFF解释为-1


总而言之,二进制级别上不存在负数。根据您选择显示二进制的方式,您可以形成负数。不过,负数只能是1和0:您无法在计算机内存单元中保存减号。

编译器将-1转换为系统正确的有符号数格式,格式为99.9%的情况下,这将是二的补码。在具有32位整数的二的补码系统上,-1将对应于0xFFFFFFFF。但如果将其存储在无符号变量中,则会得到42.9亿的值

然后尝试使用%d格式说明符打印42.9亿,该说明符保留为负数。然后程序再次将0xFFFFFF解释为-1


总而言之,二进制级别上不存在负数。根据您选择显示二进制的方式,您可以形成负数。不过,负数都是1和0:您无法将减号保存在计算机内存单元中。

正如其他人所说,您必须始终记住值和它之间的差异s表示,因为在C中这两个概念是广泛分离的

通过赋值,您将一个值放入内存的特定区域;通过printf()和类似的方法,您尝试解释这样的值

为了澄清,请尝试理解这一点:

#include <stdio.h>

int main() {   
    int val = 2181448;;
    printf("%s\n", ((char*)&val));   // * Outputs: "HI!"
    return 0;
}   
#包括
int main(){
int val=2181448;;
printf(“%s\n”((char*)&val));//*输出:“嗨!”
返回0;
}   
这将打印“HI!”,因为您将赋值放在连续的内存区域(“int”在这里至少有4个字节宽)中,数字“2181448”,十六进制为0x00214948,即:

  • 值为0x00的字节,即零
  • 值为0x21的字节,十进制为33,ascii为“!”
  • 带有0x49的字节,十进制为73,ascii为“I”
  • 最后是一个值为0x48的字节,十进制为72,ascii为“H”

如果让printf将其解释为字符串(注意强制转换只是为了避免编译器警告)(*由于反向结束)您可以看到输出的数字是一个以零结尾的4长度字符串“H”“I”!“\0”

,正如其他人所说的,您必须始终记住值与其表示形式之间的差异,因为在C中,这两个概念是广泛分开的

通过赋值,您将一个值放入内存的特定区域;通过printf()和类似的方法,您尝试解释这样的值

为了澄清,请尝试理解这一点:

#include <stdio.h>

int main() {   
    int val = 2181448;;
    printf("%s\n", ((char*)&val));   // * Outputs: "HI!"
    return 0;
}   
#包括
int main(){
int val=2181448;;
printf(“%s\n”((char*)&val));//*输出:“嗨!”
返回0;
}   
这将打印“HI!”,因为您将赋值放在连续的内存区域(“int”在这里至少有4个字节宽)中,数字“2181448”,十六进制为0x00214948,即:

  • 值为0x00的字节,即零
  • 值为0x21的字节,十进制为33,ascii为“!”
  • 带有0x49的字节,十进制为73,ascii为“I”
  • 最后是一个值为0x48的字节,十进制为72,ascii为“H”
如果你做了printfinter