最近,我读到了关于C,char / unsigned char / signed char中三种不同类型的问题。我现在遇到的问题不是我迄今为止经历过的问题(我的程序在所有经过测试的计算机上都能正常运行,并且只针对小端(基本上所有使用Windows / Linux的现代桌面和服务器都正确吗?)。我经常重复使用char我定义的数组是为了保存一个“字符串”(当然不是一个真正的字符串)作为临时变量。例如,我只是重用了一个像array [0]这样的成员,而不是向堆栈中添加另一个字符。但是,我将这个策略基于事实上,一个字母总是会被签名,直到我今天读到它实际上取决于实现。如果我现在有一个字符并给我一个负值会怎么样?
char unknownsignedness = -1;
如果我写了
unsigned char A = -1;
我认为C风格的转换将简单地重新解释比特和A代表的值,因为无符号类型变得不同。我是对的,这些C风格的演员阵容只是对比特的重新解释?我现在指的是签名< - >未签名的转化。
因此,如果某个实现的char为unsigned,我的程序是否会按预期停止工作?拿出最后一个变量,如果我现在这样做
if (A == -1)
我现在正在比较一个unsigned char和一个有符号的char值,所以这只是比较那些不关心签名的位,还是会返回false,因为很明显A不能为-1?我很困惑在这种情况下会发生什么。这也是我最关心的问题,因为我经常使用这样的字符。
答案 0 :(得分:4)
以下代码打印No
:
#include <stdio.h>
int
main()
{
unsigned char a;
a = -1;
if(a == -1)
printf("Yes\n");
else
printf("No\n");
return 0;
}
代码a = -1
为a
分配实现定义的值;在大多数机器上,a将为255.测试a == -1
将unsigned char
与int
进行比较,因此通常的促销规则适用;因此,它被解释为
`(int)a == -1`
由于a
为255,(int)a
仍为255,测试结果为false。
答案 1 :(得分:4)
unsigned char a = -1;
ISO / IEC 9899:1999在6.3.1.3/2中说:
如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值,直到该值在新类型的范围内
我们将(UCHAR_MAX+1)
添加到-1
一次,结果为UCHAR_MAX
,显然属于unsigned char
的范围。
if(a == -1)
在6.3.1.8/1中有一段很长的篇幅:
如果两个操作数具有相同的类型,则不需要进一步转换。
否则,如果两个操作数都有有符号整数类型或两者都有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。
否则,如果具有无符号整数类型的操作数的等级大于或等于 等于另一个操作数的类型的等级,然后是操作数 有符号整数类型转换为带有unsigned的操作数的类型 整数类型。
否则,如果带有符号整数类型的操作数的类型可以表示 那么,带有无符号整数类型的操作数类型的所有值 具有无符号整数类型的操作数将转换为该类型 带有符号整数类型的操作数。
否则,两个操作数都将转换为无符号整数类型 对应于带有符号整数类型的操作数的类型。
unsigned char
的排名低于int
的排名。
如果int
可以表示unsigned char
可以的所有值(通常是这种情况),那么两个操作数都会转换为int
,并且比较返回false
。
如果int
无法代表unsigned char
中的所有值,这可能会发生在sizeof(int)==sizeof(char)
的稀有机器上,那么两者都会转换为unsigned int
,-1
获取转换为UINT_MAX
,恰好与UCHAR_MAX
相同,比较返回true
。
答案 2 :(得分:3)
unsigned char A = -1;
结果为255.在分配或初始化时没有重新解释。 -1
只是两个补码表示法中的一堆1
位,其中8个是逐字复制的。
比较略有不同,因为文字-1
属于int
类型。
if (A == -1)
会在比较之前进行促销(隐式转换)(int)A
,因此最终将255与-1进行比较。不相等。
是的,你必须要谨慎对待char
。
答案 3 :(得分:-1)
我认为这个问题最好通过一个简单的例子来回答(警告:C ++,但请参阅我的推理解释):
char c = -1;
unsigned char u = -1;
signed char s = -1;
if (c == u)
printf("c == u\n");
if (s == u)
printf("s == u\n");
if (s == c)
printf("s == c\n");
if (static_cast<unsigned char>(s) == u)
printf("(unsigned char)s == u\n");
if (c == static_cast<char>(u))
printf("c == (char)u\n");
输出:
s == c
(unsigned char)s == u
c == (char)u
C在按原样使用时对值的处理方式不同,但你是正确的,因为转换只会重新解释这些位。我在这里使用了C ++ static_cast
来表明编译器可以执行此转换。在C中,您可以通过在括号中为该类型添加前缀来进行强制转换。没有编译器检查以确保转换在C中是安全的。