C演员和char签名

时间:2015-01-01 18:11:13

标签: c char signedness

最近,我读到了关于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?我很困惑在这种情况下会发生什么。这也是我最关心的问题,因为我经常使用这样的字符。

4 个答案:

答案 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 = -1a分配实现定义的值;在大多数机器上,a将为255.测试a == -1unsigned charint进行比较,因此通常的促销规则适用;因此,它被解释为

`(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中是安全的。