2012-07-29 116 views
1
#include<stdio.h> 

main() 
{ 
     unsigned x=1; 
     signed char y=-1; 
     clrscr(); 
     if(x>y) 
     printf("x>y"); 
     else 
    printf("x<=y"); 
} 

有符号字符的值从-128增加到127.所以预期输出应该是'x> y',但它不是。编译器给出输出 - “x < = y”。你能解释为什么吗?为什么输出错误?

回答

7

在比较signed char得到转换为unsigned int,因此看起来像一个非常大的价值。我希望编译器能够警告你 - 例如,“比较已签名和未签名的东西是令人困惑的”。

这种转换是根据“关系运算符”规定:

如果两个操作数的算术具有类型,通常的 算术转换被执行。

+0

对不起,编译器不警告。它只是给出了提到的输出。我正在使用Codeblocks编译器。谢谢您的回答。 – Niteesh 2012-07-29 12:34:44

0

作为比较,如果一个操作数是无符号的,则另一个操作数如果其类型被签名,则隐式转换为无符号!

更多地在这里找到:Signed/unsigned comparisons

0

在你的情况有符号的字符转换为unsigned int类型,所以我们得到一个大的正整数,而不是-1。这里是ANSI C标准草案的一个摘录,它解释了在发生常规算术转换期间发生的事情。

3.2.1.5常见的算术转换

许多双目操作符,期待 转化和产量的结果类型以类似的方式的算术类型原因操作数。目的是产生一个通用的类型,这也是结果的类型,即 。这种 模式被称为通常的算术转换:首先,如果任一 操作数的类型为long double,则另一个操作数转换为长整数 double。否则,如果任一操作数的类型为double,则另一个操作数将转换为double。否则,如果任一操作数的类型为 float,则另一个操作数转换为float。否则, 积分促销在两个操作数上执行。然后 应用下列规则:如果任一操作数的类型无符号长 int,则另一个操作数转换为unsigned long int类型。否则,如果 一个操作数的类型长int和另一个具有unsigned int类型, 如果一个长整型可以表示一个unsigned int的所有值,操作数 类型的无符号整型转换为长整型;如果long int不能 表示无符号整型的所有值,则两个操作数都是 转换为unsigned long int。否则,如果任一操作数的类型为 long int,则另一个操作数将转换为long int。 否则,如果任一操作数的类型为unsigned int,则另一个操作数转换为unsigned int。否则,两个操作数都有 int类型。

2

C11§6.8AL3 P95:

如果两个操作数的算术具有类型,通常的算术转换为执行 。

C11§6.3.1.8AL1的p53:

[...]如果具有无符号整数类型操作数的秩大于或 等于所述其他的类型的秩操作数,那么带有符号整数类型的操作数 将转换为具有无符号整数类型的 操作数的类型。

所以y将促进为无符号类型,并且将大于x1)。

0

获取用于所有的警告,即在GCC的情况下进行编译:

gcc -Wall -Wextra -pedantic source.c -o prog 

在你的情况-Wextra提供以下信息标志:

warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 

这并不能解释为什么,但至少会警告你;)。

解释是,与关系运算符相比,评估为-1的带符号变量等于无符号评估值UINT_MAX

编译器必须做在这种情况下,明确的东西,这就是人们想出了...

0

当编译器看到有符号整数它促进符号int无符号比较一个unsigned int,这意味着要添加这个(在Linux机器)已签署的一个:

#define UINT_MAX (~0U) (defined in this header file : /include/linux/kernel.h) 

所以,现在你是比较UINT_MAX - 与X,这清楚地解释输出1(UINT_MAX + Y)

编辑:更加清楚:在32位机器--->UINT_MAX = 2 147 483 648 = 2**31

问候。