2009-09-01 38 views
1

我有一个小样本函数:如何强制类型转换文字用C

#define VALUE 0 

int test(unsigned char x) { 
    if (x>=VALUE) 
    return 0; 
    else 
    return 1; 
} 

我的编译器警告我说的比较(X> = VALUE)在所有情况下是真实的,哪些是对的,因为X是一个无符号的字符和值与值0定义所以我改变了我的代码:

if (((signed int) x) >= ((signed int) VALUE)) 

但警告再来。我测试了三个GCC版本(所有版本> 4.0,有时您必须启用-Wextra)。

在改变的情况下,我有这个明确的转换,它应该是一个有符号的int比较。为什么它声称比较总是正确的?

+0

那么,你想完成什么?你想在什么条件下返回1而不是0? – 2009-09-01 13:21:54

+0

我的意图是摆脱这个警告。 – 2009-09-01 13:31:10

+3

不要摆脱这个警告,试图摆脱你需要知道一个无符号是否大于等于0.它总是 - 这就是编译器告诉你的。 – xtofl 2009-09-01 13:35:25

回答

9

即使对于演员来说,在所有已定义行为的情况下,比较依然如此。编译器仍然确定(signed int)0的值为0,并且如果程序具有已定义的行为(如果该值超出签名类型的范围,则从unsigned到signed的转换未定义)仍然确定(signed int)x)为非负数。

所以编译器会继续发出警告,因为它会继续消除else情况。

编辑:沉默警告,编写代码为

#define VALUE 0 

int test(unsigned char x) { 
#if VALUE==0 
    return 1; 
#else 
    return x>=VALUE; 
#endif 
} 
+0

一个'unsigned char'值可能永远不会超出'signed int'的范围。即使符号位已设置,该值也在“signed int”的范围内,并且操作始终定义良好(并且结果始终为正值)。 – 2009-09-01 13:22:43

+0

糟糕,我错过了它是从char到int。尽管如此,这可能发生在sizeof(int)== 1的C(理论)实现上。由于int必须至少有2个八位字节,所以在一个字符也是两个八位字节的实现中这是可能的。我同意在现实的平台上,这里不会发生溢出。 – 2009-09-01 13:37:54

1

VALUE0#define意味着你的功能降低这样:

int test(unsigned char x) { 
    if (x>=0) 
    return 0; 
    else 
    return 1; 
} 

由于x总是传递作为unsigned char,那么它将永远有0255包容性之间的值,而不管是否在if声明中将x0转换为signed int。编译器因此警告您,x将始终大于或等于0,并且else子句永远无法到达。

11

我认为GCC是在这种情况下

3

xunsigned char比你聪明,这意味着它是0和256之间由于int大于char,因此铸造unsigned charsigned int仍保留char的原始值。由于此值始终> = 0,因此您的if始终为真。

1

unsigned char的所有值都可以在您的int中完美呈现,因此即使是演员阵容,您也永远不会得到负值。您需要的演员阵容是signed char - 但是,在这种情况下,您应该在功能签名中声明xsigned。对客户说谎是没有意义的,你需要一个无符号的值,而实际上你需要一个有符号的值。