1

我在下面写了一个小程序。

#include <stdio.h>
main(){
    char a=-1;
    unsigned char b=-1;
    printf("%d %d\n",a,b);
    printf("%x %x\n",a,b);
    if(a==b) printf("equal\n");
    else printf("not equal\n");
}

prog的输出是:

-1 255
ffffffff ff
not equal

由于 char 只有一个字节,而 -1 以 2 的补码形式表示,我认为 0xff 将存储在 a 和 b 中,因此两者应该相等。谁能让我知道它们为什么不同以及为什么 a 的十六进制表示是 0xffffffff 而不是 0xff。我得到了一个相关链接http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/但我无法得到答案。任何帮助将不胜感激。谢谢。

4

4 回答 4

5

他们是一样的。或者更确切地说,它们的底层表示是相同的(假设您的编译器使用二补码形式)。

另一方面,它们代表的值是 -1 和 255。

当您打印它们时,它们会扩展到数据类型intunsigned char是零扩展的,而有符号字符是符号扩展的,这说明了您看到的差异。

比较两个值时会发生相同的扩展。a == b不要比较底层表示,而是将两个值都扩展为,int因此它将 255 与 -1 进行比较,这不相等。

请注意,plainchar可以是已签名或未签名的。在您的环境中,它显然已签名。

于 2013-01-09T12:30:51.377 回答
2

char类型有点异常,因为它与signed charorunsigned char不同(与其他整数类型不同 - short, int,long等 - 除非明确声明,否则它们是隐式签名的unsigned)。是否char实际签名取决于实现,一些编译器甚至允许您通过命令行开关指定签名。

底线:永远不要假设它char是有符号或无符号的 - 如果您实际上需要有符号或无符号的 8 位数量,则使用signed charorunsigned char显式,或者更好的是,使用int8_tor uint8_tfrom <stdint.h>

于 2013-01-09T12:26:43.767 回答
2

Asigned int有符号,anunsigned int无符号。如果使用just int,则暗示signed intshort,long或也是如此long long。然而它不是真的char。Asigned char是有符号的,anunsigned char是无符号的,但char可以是有符号的或无符号的。数据类型 char 应该包含一个“字符”,因此是名称,因此它不是“真正的”整数类型来保存要用于计算的整数。当然,字符实际上是某种整数,但哪种整数取决于实现(C 标准不强制任何特定类型)。因此,如果您想将 char 类型用于整数值(也用于计算),请始终使用signed charorunsigned char显式并且仅使用char当您真正处理字符时,或者如果 char 是有符号或无符号的,它对您的代码完全没有影响。

比较失败,因为您的实现定义char为 in fact signed char,因此您在最终语句中将 a 与 asigned char进行比较。每当您比较两个不同类型的整数时,编译器都会在实际执行比较之前根据 C 标准的规则将这两个值转换为相同类型。在您的情况下,这意味着 C 编译器实际上执行以下操作:unsigned charif

if((int)a==(int)b) printf("equal\n");
    else printf("not equal\n");
}

现在应该很明显为什么这两个值不匹配了。(int)a的值为-1,但(int)b值为255,并且这两个值不相等。

根据类型提升的规则,char(在你的情况下签名)被提升为int并且unsigned char也被提升为int。ISO C 2011 标准说:

如果 int 可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为 int;否则,它将转换为无符号整数。这些被称为整数提升。)所有其他类型都不受整数提升的影响。

整数促销保留价值,包括符号。如前所述,''plain'' char 是否被视为有符号是实现定义的。

于 2013-01-09T12:39:48.773 回答
0

虽然在普通的“char”周围存在一些歧义(请参阅Is char signed or unsigned by default?),但我认为这并不是唯一发生的事情。

文字 -1 是一个整数,它不会(sizeof(int)>sizeof(char),为了参数)“适合”到一个字符中。双补码位模式 0xffff(为了参数,32 位 int)是在这里截断并复制。

当您调用 printf() 时,参数被提升为整数类型,有符号类型是“符号扩展”,但无符号“b”不是,并且填充了零。当您将“==”与两种不同的类型一起使用时,会执行类似(但不一定相同)的类型转换(也称为“通常的算术转换”)。

另请参阅C 函数调用中的默认参数提升和有符号和无符号,以及位扩展如何在 C中工作。

于 2013-01-09T12:48:06.347 回答