在C程序中,如果整数为signed integer
,则最高位为1
,否则为0
。
让我们char
和unsigned char
,signed char
的范围为-128
至127
,unsigned char
为0
至255
,但实际上他们的十六进制范围为0x00
到0xff
。
我现在的问题是,如果char
和unsigned char
使用8位二进制数存储在内存中,那么计算机本身如何知道它是signed
还是unsigned
?
char a = 0xff; printf("%d", a); //its result is -1.
unsigned char a = 0xff; printf("%d", a); //its result is 255.
在上面的示例中,printf
如何知道0xff
的值是已签名还是未签名?这仅取决于a
的定义吗?
答案 0 :(得分:6)
此处有许多相关问题,例如this一个。
您的问题不太恰当:对于signed
,最高位并不总是1
- 仅当值为负时。事实上,signed
或unsigned
是"类型"归因于完全相同的位模式,以及这些位模式在比较或提升时如何解释 由它们各自的类型定义。
例如:
unsigned char u = 0xFF; // decimal 255
signed char s = 0xFF; // decimal -1
您可以在最高位设置中看到两个值是如何相同的,但它们的类型不同。
编译器使用type system来了解如何解释值,程序员的任务是为值分配有意义的类型。在上面的示例中,我告诉编译器第一个0xFF
应该被解释为unsigned
值(另请参见包含文件limits.h),其中包含最大值:
u = 0x00; // decimal 0, CHAR_MIN
u = 0xFF; // decimal 255, UCHAR_MAX
和第二个0xFF
作为signed
值,具有最大范围:
s = 0x00; // decimal 0, CHAR_MIN
s = 0x7F; // decimal 127, SCHAR_MAX
s = 0x80; // decimal -127, SCHAR_MIN (note how 0x7F + 1 = 0x80, decimal 127 + 1 = -127, called an overflow)
s = 0xFF; // decimal -1
对于示例中的printf,%d
告诉它期望signed int
值。根据{{3}},较小的char
类型可以是符号扩展(如果它是signed
类型)或零扩展(如果它是unsigned
printf("%d", u); // passes a int 0x000000FF, decimal 128, to the function
printf("%d", s); // passes a int 0xFFFFFFFF, decimal -1, to the function
})。完成上面的例子:
%u
更多printf格式说明符为integer promotion rules of the C language,例如{{1}}在此上下文中可能对您有用。
答案 1 :(得分:4)
在printf()
电话(和其他场合),适用整数提升规则。
编译器将给定值转换为int
。这取决于char的签名(当然,编译器已知)。因此,根据char的签名,编译器通过填充0
位或char的最高位来完成转换。
答案 2 :(得分:3)
在C程序中,如果整数是有符号整数,则最高位为1,否则为0。
此声明不正确。
在C程序中,如果整数是负有符号整数,则最高位为1,否则为0.
此声明也不正确。
在使用二进制补码有符号整数的C程序中,如果整数是负有符号整数,则最高位为1,否则为0.
这是正确的。
让我们使用char和unsigned char,signed char的范围是-128到127,unsigned char是0到255,但实际上它们的十六进制在0x00到0xff的范围内。
这句话令人困惑和误导。 0xFF
只是编写128的另一种方式。你也可以说“在十六进制中,有符号字符的范围是-0x80
到0x7F
,而签名字符是{{1转到0x00
。“
现在的问题是,如果使用8位二进制数将char和unsigned char存储在内存中,计算机本身如何知道它是已签名还是未签名?
电脑不知道。 您通过输入单词0xFF
告诉您是否要将该内存解释为有符号数字或无符号数字。
在上面的例子中,printf如何知道0xff的值是有符号还是无符号?
离开unsigned
。让我们举一个更简单的例子:
printf
会发生什么? 128大于最大可能的有符号字符(再次假设二进制补码中有8位字符)。因此值包含到最小可能值;这变成-128。
char a = 128;
会发生什么? 129大于 two 的最大可能签名字符。所以它包围了第二个可能的最小值,-127。
char a = 129;
三大于最大可能值,因此它包围第三个可能的最小值,-126。
....跳过几个......
char a = 130;
这比最大可能值大128,因此它包围到第128个最小可能值,即-1。
知道了吗?
好的,现在我们明白了:
char a = 255;
现在当我们说
时会发生什么char a = 255;
unsigned char b = 255;
?我们有一个有符号整数。 int c = a;
int d = b;
我们已经确定已经回绕到-1,它在整数范围内,因此a
变为整数-1。 c
是unsigned char 255,它在整数范围内,因此b
变为整数d
。
255
和a
的内存内容相同这一事实无关紧要。根据您分配给b
和a
的类型,该内存被解释为数字。特别是,该位模式到整数位模式的转换完全取决于类型。