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

Different Data Types - Signed and Unsigned

我刚刚执行了下面的代码

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=?

不同

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

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

char 存储从 -128 到 127,unsigned char 存储从 0 到 255。 0xfb代表十进制的251,超出了char a.

的限制

有两种情况需要考虑:

  • 如果 char 类型默认是无符号的,ab 都会被赋值为 251,程序将打印 Same
  • 如果 char 类型是默认签名的,唉,这是最常见的情况,定义 char a = 0xfb; 具有实现定义的行为,如 0xfb251 在decimal) 可能超出了 char 类型的范围(通常是 -128127)。很可能值 -5 将存储到 a 并且 a == b 计算为 0 因为两个参数在比较之前都被提升为 int,因此 -5 == 251 将为假。

printf("a=%c,b=%c", a, b); 的行为也取决于系统,因为非 ASCII 字符 -5251 可能会以意想不到的方式打印。但是请注意,两者都将打印相同的内容,因为 %c 格式指定参数在打印前转换为 unsigned char。尝试 printf("a=%d, b=%d\n", a, b);

会更安全、更明确

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

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

4 If both of the operands have arithmetic type, the usual arithmetic conversions are performed....

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

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

2 The following may be used in an expression wherever an int or unsigned int may be used: ...

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.58) All other types are unchanged by the integer promotions.

所以在这个等式表达式中

a == b

两个操作数都转换为类型int。带符号的操作数(假设类型 char 的行为与类型 signed char 相同)通过传播符号位的方式转换为类型 int

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

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