不同的数据类型 - 有符号和无符号

Different Data Types - Signed and Unsigned

提问人:NithinR 提问时间:9/13/2017 最后编辑:Vlad from MoscowNithinR 更新时间:9/13/2017 访问量:345

问:

我刚刚执行了以下代码

main()
{
   char a = 0xfb;
   unsigned char b = 0xfb;
   printf("a=%c,b=%c",a,b);
   if(a==b) {
     printf("\nSame");
   }
   else {
     printf("\nNot Same");
   }
}

对于这段代码,我得到的答案是

一个=?b=?

不同

为什么我没有得到相同,a 和 b 的值是多少?

c 运算符 相等 整数提升

评论

1赞 krpra 9/13/2017
读一本好的C书,了解不同数据类型的内存表示以及数据类型和数据类型之间的区别signedunsigned
3赞 alk 9/13/2017
"“不同”真的吗?
0赞 chux - Reinstate Monica 9/13/2017
“A 和 B 的值是多少”可以很容易地用printf("a=%d,b=%d",a,b);

答:

6赞 Lee Daniel Crocker 9/13/2017 #1

这条线...在比较之前将字符提升为整数,因此字符的符号会影响这种情况的发生方式。无符号字符 0xFB 变为整数 251;有符号字符 0xFB 变为整数 -5。因此,它们是不平等的。if (a == b)

评论

0赞 chux - Reinstate Monica 9/13/2017
签名字符在 之前变为 -5,但在 time 时变为 -5。if (a == b)char a = 0xfb;
0赞 Lee Daniel Crocker 9/13/2017
在某种程度上,是的。单字节0xFB被正确解释为 -5,即使存储在一个字节中也是如此。这就是为什么在升级完成后,它在物理上扩展到0xFFFFFFFB,而另一个在物理上扩展到0x000000FB。
0赞 chqrlie 9/13/2017
这就是为什么在促销完成后,它会在物理上扩展到0xFFFFFFFB也许,也许不是。该行为不依赖于内存中整数的大小,也不依赖于整数的表示形式。存储到有符号的 8 位具有实现定义的行为,这在大多数当前架构中意味着存储,其余部分在所有架构上都是完全定义的。int0xfbchar-5
0赞 Lee Daniel Crocker 9/13/2017
是的,我假设很多东西,比如 2s 补码二进制和 32 位整数等,对提问者来说可能是正确的。但一如既往,如果可以的话,C 可以自由地以不同的方式做到这一点。
0赞 krpra 9/13/2017 #2

char存储从 -128 到 127,存储从 0 到 255。 并表示十进制 251,超出了 的限制。unsigned char0xfbchar a

4赞 chqrlie 9/13/2017 #3

有 2 种情况需要考虑:

  • 如果默认情况下类型为 unsigned,则为 both 和 分配值,程序将打印 .charab251Same
  • 如果类型默认是签名的,这是最常见的情况,则定义具有实现定义的行为 AS ( 以十进制表示) 可能超出了该类型的范围 (通常为 )。最有可能的是,该值将被存储到并计算为,因为两个参数都在比较之前被提升到,因此将是假的。charchar a = 0xfb;0xfb251char-128127-5aa == b0int-5 == 251

的行为也与非 ASCII 字符一样依赖于系统,并且可能会以意想不到的方式打印(如果有的话)。但请注意,两者都将打印相同,因为格式指定在打印之前将参数转换为。尝试会更安全、更明确printf("a=%c,b=%c", a, b);-5251%cunsigned charprintf("a=%d, b=%d\n", a, b);

使用 gcc 或 clang,您可以尝试重新编译您的程序,看看行为会有什么不同。-funsigned-char

评论

0赞 chux - Reinstate Monica 9/13/2017
就其解决具有实现定义行为的问题而言,最佳答案。a = 0xfb;
2赞 Vlad from Moscow 9/13/2017 #4

根据 C 标准(6.5.9 相等运算符)

4 如果两个操作数都具有算术类型,则通常的算术 执行转换...。

通常的算术转换包括整数提升。

来自 C 标准(6.3.1.1 布尔值、字符和整数)

2 以下可以在表达式中使用,只要 int 或 可以使用无符号 int: ...

如果 int 可以表示原始类型的所有值(作为限制 通过宽度,对于位字段),该值将转换为 int; 否则,它将转换为无符号 int。 这些称为 整数提升。58) 所有其他类型都按整数保持不变 促销。

所以在这个等式表达中

a == b

这两个操作数都转换为类型 。有符号操作数(前提是类型的行为与类型一样)通过传播符号位转换为类型。intcharsigned charint

因此,由于二进制表示的差异,操作数具有不同的值。

如果类型的行为与类型相同(例如,通过设置编译器的相应选项),那么显然操作数将是相等的。charunsigned char

评论

0赞 chqrlie 9/13/2017
因此,由于二进制表示的差异,操作数具有不同的值。更准确地说,由于对二进制表示的解释不同。