如何确定变量是已签名还是未取消

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

让我们使用charunsigned charsigned char的范围是-128127unsigned char0255 ,但实际上它们的hex在0x000xff范围内。 我现在的问题是,如果使用8位二进制数将charunsigned char存储在内存中,计算机本身如何知道它是已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 ?的定义?

这里有许多相关的问题,例如这个问题。

你的问题不太正确:对于signed ,最高位并不总是1 – 只有当值为负时。 实际上,有signedunsigned是归因于完全相同的位模式的“类型”,并且在比较或提升时如何解释这些位模式由它们各自的类型定义。

例如:

 unsigned char u = 0xFF; // decimal 255 signed char s = 0xFF; // decimal -1 

您可以在设置的最高位中看到两个值是如何相同的,但它们的类型不同。

编译器使用类型系统来了解如何解释值,程序员的任务是为值分配有意义的类型。 在上面的例子中,我告诉编译器第一个0xFF应该被解释为unsigned值(参见include文件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值。 根据C语言的整数提升规则,较小的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 

这里有更多printf格式说明符,例如%u在这种情况下可能对你有意义。

printf()调用(和其他场合)上,适用整数提升规则。

编译器将给定值转换为int 。 这取决于char的签名(当然,编译器已知)。 因此,根据char的签名,编译器通过填充0位或char的最高位来完成转换。

在C程序中,如果整数是有符号整数,则最高位为1,否则为0。

这个说法不正确。

在C程序中,如果整数是负有符号整数,则最高位为1,否则为0。

这个陈述也是不正确的。

在使用二进制补码有符号整数的C程序中,如果整数是负有符号整数,则最高位为1,否则为0。

那是对的。

让我们使用char和unsigned char,signed char的范围是-128到127,unsigned char是0到255,但实际上它们的hex在0x00到0xff的范围内。

这种说法令人困惑和误导。 0xFF只是编写128的另一种方式。你也可以说“在hex中,有符号字符的范围是-0x800x7F ,而有符号字符的范围是0x000xFF 。”

我现在的问题是,如果使用8位二进制数将char和unsigned char存储在内存中,计算机本身如何知道它是已签名还是未签名?

电脑不知道。 可以通过键入unsigned一词来告诉它是否要将该内存解释为带符号数或无符号数。

在上面的例子中,printf如何知道0xff的值是有符号还是无符号?

printf删除。 让我们举一个更简单的例子:

 char a = 128; 

怎么了? 128大于最大可能的有符号字符(再次假设二进制补码中有8位字符)。 因此,值包含在尽可能小的值 ; 这变成-128。

 char a = 129; 

怎么了? 129比最大可能的签名字符大2 。 所以它包围了第二个可能的最小值 -127。

 char a = 130; 

这比最大可能值大3,因此它包含到第三个可能的最小值 -126。

….跳过几个……

 char a = 255; 

这比最大可能值大128,因此它包围到第128个最小可能值,即-1。

得到它了?

好了,现在我们明白了:

 char a = 255; unsigned char b = 255; 

现在,当我们说时会发生什么

 int c = a; int d = b; 

? 我们有一个有符号整数。 我们已经确定已经回绕到-1,它在整数范围内,因此c变为整数-1。 b是无符号字符255,它在整数范围内,因此d变为整数255

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