不同的数据类型 - 有符号和无符号
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
类型默认是无符号的,a
和 b
都会被赋值为 251
,程序将打印 Same
。
- 如果
char
类型是默认签名的,唉,这是最常见的情况,定义 char a = 0xfb;
具有实现定义的行为,如 0xfb
(251
在decimal) 可能超出了 char
类型的范围(通常是 -128
到 127
)。很可能值 -5
将存储到 a
并且 a == b
计算为 0
因为两个参数在比较之前都被提升为 int
,因此 -5 == 251
将为假。
printf("a=%c,b=%c", a, b);
的行为也取决于系统,因为非 ASCII 字符 -5
和 251
可能会以意想不到的方式打印。但是请注意,两者都将打印相同的内容,因为 %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
相同(例如通过设置编译器的相应选项),那么显然操作数将相等。
我刚刚执行了下面的代码
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
类型默认是无符号的,a
和b
都会被赋值为251
,程序将打印Same
。 - 如果
char
类型是默认签名的,唉,这是最常见的情况,定义char a = 0xfb;
具有实现定义的行为,如0xfb
(251
在decimal) 可能超出了char
类型的范围(通常是-128
到127
)。很可能值-5
将存储到a
并且a == b
计算为0
因为两个参数在比较之前都被提升为int
,因此-5 == 251
将为假。
printf("a=%c,b=%c", a, b);
的行为也取决于系统,因为非 ASCII 字符 -5
和 251
可能会以意想不到的方式打印。但是请注意,两者都将打印相同的内容,因为 %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
相同(例如通过设置编译器的相应选项),那么显然操作数将相等。