2015-01-01 44 views
0

所以最近,我读了一个关于C,char/unsigned char/signed char中三种不同类型的问题。我现在遇到的问题并不是我迄今为止所经历过的(我的程序在所有测试过的计算机上都能正常工作,并且只针对小端(基本上所有使用Windows/Linux的现代台式机和服务器都适用?)。我经常重复使用char我为定义一个“字符串”(当然不是一个真正的字符串)作为临时变量定义的数组,例如,不是将另一个字符添加到堆栈中,而是重用像array [0]这样的成员之一。事实上,一个char总是签署,直到今天我读它实际上取决于实现。如果我现在有一个char和我分配一个负值,会发生什么?C cast和char signedity

char unknownsignedness = -1; 

如果我写的

unsigned char A = -1; 

我认为C风格的演员将简单地重新解释位和A表示为无符号类型的值变得不同。我认为这些C型表演只是对位的重新解释吗?我现在指的是签署< - >无符号转换。

所以如果一个实现有char作为无符号,我的程序会按预期停止工作吗?就拿最后一个变量,如果我现在做

if (A == -1) 

我现在比较一个无符号字符到符号的字符值,所以会这样简单地比较不关心是否带符号位还是将返回false,因为显然不能是-1?我很困惑在这种情况下会发生什么。这也是我最关心的问题,因为我经常使用这样的字符。

+2

什么铸造?没有任何地方铸造。如果要存储二进制(非字符)数据,请使用更好的(IMO)'int8_t'或'uint8_t'标准类型。 –

+0

我的实现不支持C99,我认为int8_t是该版本 – user209347

+0

如果我将一个有符号的值赋给一个无符号的值,会不会有转换?或者只有在数据大小不匹配的情况下才会投射? – user209347

回答

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 == -1unsigned charint进行比较,因此通常的促销规则适用;因此,它被解释为

`(int)a == -1` 

由于a是255,(int)a仍然是255,并且测试产生false。

+0

“代码a = -1”对不对? – user209347

+0

@ user209347修好了,谢谢。 – jch

+0

“实现定义的值”在所有符合的实现中,这将是“UCHAR_MAX”。 –

-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.

+1

这是一个C问题。 C和C++是不同的语言。 – jch

+0

@jch:阅读第一行说明在本例中查看使用C++的解释。 – greg

+0

因此,如果我从“A == -1”这个问题中拿出我的例子,我必须明确地将其转换为“(signed char)A == -1”才能使其工作? – user209347

3
unsigned char A = -1; 

结果为255.在赋值或初始化时没有重新解释。一个-1只是一堆1位的二进制补码表示,其中8个是逐字复制的。

比较有点不同,因为文字-1int类型。

if (A == -1) 

会做促销(隐式转换)(int)A比较之前,所以你最终-1比较255。不等于。

是的,你必须小心与普通char

+2

“结果为255”。那就是如果你的char是8位。不保证。 “8位机器,其中'sizeof(int)== sizeof(char)'”。 “int”至少为16位。 –

+0

同意。我认为char是8位。有没有人见过不同的东西?编辑。 – SzG

+0

“有人见过不同的东西吗?”可能的重复:http://stackoverflow.com/questions/2098149/what-platforms-have-something-other-than-8-bit-char –

4
unsigned char a = -1; 

ISO/IEC 9899:1999说,在6.3.1.3/2:

如果新类型是无符号的,所述值是通过反复增加或减去 比最大值多一个转换可在新的类型来表示,直到该值是新类型的范围

我们添加(UCHAR_MAX+1)-1一次,结果是UCHAR_MAX,这显然是范围为unsigned char

如果(A == -1)

还有很长的通道中6.3.1.8/1:

如果两个操作数具有相同的类型,则不需要进一步的转化。否则,如果两个操作数具有有符号整数类型或两者都具有无符号整数类型 ,则类型为较小整数转换等级的操作数为 转换为具有较高等级的操作数的类型。

否则,如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数的类型的秩,然后用 符号整型操作数被转换为操作数的类型与无符号 整数类型。

否则,如果用符号整型操作数的类型可以表示 所有与无符号整数类型的操作数的类型的值,则 与无符号整数类型的操作数被转换到 的类型带有符号整数类型的操作数。

否则,两个操作数都转换为无符号整数类型 ,对应于带有符号整数类型的操作数的类型。

unsigned char的排名小于int的排名。

如果int可以表示unsigned char能(其通常是这种情况),那么两个操作数都转换为int的所有值,并且比较返回false

如果int不能代表所有值unsigned char,它可以在罕见的机器发生与sizeof(int)==sizeof(char),那么两者都转化为unsigned int-1被转换为UINT_MAX这恰好是一样UCHAR_MAX,并且比较返回true