如何确定变量是有符号还是无符号

时间:2014-03-19 05:51:56

标签: c unsigned

在C程序中,如果整数为signed integer,则最高位为1,否则为0

让我们charunsigned charsigned char的范围为-128127unsigned char0255,但实际上他们的十六进制范围为0x000xff。 我现在的问题是,如果charunsigned 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的定义吗?

3 个答案:

答案 0 :(得分:6)

此处有许多相关问题,例如this一个。

您的问题不太恰当:对于signed,最高位并不总是1 - 仅当值为负时。事实上,signedunsigned是"类型"归因于完全相同的位模式,以及这些位模式在比较或提升时如何解释 由它们各自的类型定义。

例如:

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的另一种方式。你也可以说“在十六进制中,有符号字符的范围是-0x800x7F,而签名字符是{{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

255a的内存内容相同这一事实无关紧要。根据您分配给ba类型,该内存被解释为数字。特别是,该位模式到整数位模式的转换完全取决于类型。