#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");
}
编程的输出是:
-1 255
ffffffff ff
not equal
因为char只有一个字节而-1用2的补码形式表示,我认为0xff将存储在a&amp; b因此两者应该是平等的。任何人都可以让我知道为什么他们是不同的,为什么十六进制的一个是0xffffffff&amp;不是0xff。我有一个相关的链接http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/,但我无法得到答案。任何帮助将不胜感激。感谢。
答案 0 :(得分:5)
他们是一样的。或者更确切地说,它们的底层表示是相同的(假设您的编译器使用双补码形式)。
另一方面,它们代表的值是-1和255。
当您打印它们时,它们扩展到数据类型int
。 unsigned char
为零扩展,而签名字符是符号扩展,这可以解释您看到的差异。
比较两个值时会发生相同的扩展。 a == b
不比较底层表示,而是将两个值都扩展为int
,因此它将255与-1进行比较,这是不相等的。
请注意,普通char
可以是签名的也可以是未签名的。在您的环境中,它显然是签名的。
答案 1 :(得分:2)
char
类型有点异常,因为它与signed char
或unsigned char
不同(与其他整数类型不同 - short
,{{ 1}},int
等 - 除非明确声明long
,否则将被隐式签名。 unsigned
是否实际签名是依赖于实现的,有些编译器甚至允许您通过命令行开关指定签名。
底线:永远不要假设char
已签名或未签名 - 如果您确实需要有符号或无符号8位数量,请明确使用char
或signed char
,或者更好地使用来自unsigned char
的{{1}}或int8_t
。
答案 2 :(得分:2)
signed int
已签名,unsigned int
未签名。如果仅使用int
,则表示signed int
。 short
,long
或long long
也是如此。但char
并非如此。 signed char
已签名,unsigned char
未签名,但只有char
可以是已签名或未签名。数据类型char应该包含“字符”,因此名称,因此它不是“真正”整数类型来保存要在计算中使用的整数。当然,角色实际上是某种类型的整数但是依赖于实现的类型(C标准不强制任何特定种类)。因此,如果您希望将char类型用于整数值(也用于计算),请始终明确使用signed char
或unsigned char
,并在实际处理字符时仅使用char
或如果char签名或未签名,它对你的代码完全没有区别。
比较失败,因为您的实现将char
定义为signed char
,因此您要将signed char
与unsigned char
中的if
进行比较if((int)a==(int)b) printf("equal\n");
else printf("not equal\n");
}
声明。每当您比较两个不同类型的整数时,编译器在实际执行比较之前将两个值都转换为相同的类型according to the rules of the C standard。在您的情况下,这意味着C编译器实际执行以下操作:
(int)a
现在很明显为什么这两个值不匹配。 -1
的值为(int)b
,但255
的值为char
,且这两个值不相等。
根据类型促销的规则,int
(在您签名的情况下)被提升为unsigned char
,int
也被提升为{{1} }}。 ISO C 2011标准说:
如果int可以表示原始类型的所有值(限制为 通过宽度,对于位字段),该值被转换为int; 否则,它将转换为unsigned int。这些被称为 整数提升。)所有其他类型的整数不变 促销。
整数促销保留包括符号在内的值。如上所述 之前,“普通”字符是否被视为已签名 实现定义的。
答案 3 :(得分:0)
虽然围绕一个普通的“char”(见Is char signed or unsigned by default?)存在一些模糊性,但这并不是我认为的唯一的事情。
文字-1是一个整数,它不会(sizeof(int)&gt; sizeof(char),为了参数)“适合”到char。双补码位模式0xffff(32位int为在这里截断并复制参数缘故。
当你调用printf()时,参数被提升为整数类型,有符号类型是“符号扩展”,但是无符号“b”不是,并且填充为零。当您对两个不同类型使用“==”时,会执行类似(但不一定相同)的类型转换(也就是“通常的算术转换”)。
另请参阅Default argument promotions in C function calls和Signed and unsigned, and how bit extension works in C。