为什么输出错了?

时间:2012-07-29 12:30:16

标签: c types

#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&gt; y',但事实并非如此。编译器给出输出 - “x&lt; = y”。你能解释一下原因吗?

6 个答案:

答案 0 :(得分:7)

在比较中,signed char被转换为unsigned int,因此看起来非常重要。我希望编译器能够警告你 - 也就是说“比较有符号和无符号的东西”这一点令人困惑。

此转换是在“关系运算符”下强制执行的:

  

如果两个操作数都有算术类型,那么通常   进行算术转换。

答案 1 :(得分:2)

C11§6.8al3p95:

  

如果两个操作数都有算术类型,则通常的算术转换是   进行。

C11§6.3.1.8al1p53:

  

[...]如果具有无符号整数类型的操作数的排名更高   或者等于另一个操作数的类型的等级,然后是   带有符号整数类型的操作数转换为   具有无符号整数类型的操作数。

因此,y将被提升为无符号类型,并且将大于x1)。

答案 2 :(得分:0)

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

在此处找到更多内容:Signed/unsigned comparisons

答案 3 :(得分:0)

在你的情况下,signed char被转换为unsigned int,因此我们得到一个大的正整数而不是-1。以下是ANSI C标准草案的摘录,解释了在通常的算术转换过程中发生的情况。

  

3.2.1.5常用算术转换

     

许多期望算术类操作数的二元运算符会导致   以类似的方式转换和生成结果类型。目的是   产生一个公共类型,这也是结果的类型。这个   模式称为通常的算术转换:首先,如果是   操作数的类型为long double,另一个操作数转换为long   双倍。否则,如果任一操作数的类型为double,则另一个   操作数转换为double。否则,如果任一操作数具有类型   float,另一个操作数转换为float。否则,   在两个操作数上执行整体促销。那么   应用以下规则:如果任一操作数的类型为unsigned long   int,另一个操作数转换为unsigned long int。除此以外,   如果一个操作数的类型为long int而另一个操作数的类型为unsigned int,   如果long int可以表示unsigned int的所有值,那么操作数   unsigned int类型转换为long int;如果一个长int不能   表示无符号整数的所有值,两个操作数都是   转换为unsigned long int。否则,如果任一操作数具有类型   long int,另一个操作数转换为long int。   否则,如果任一操作数的类型为unsigned int,则另一个操作数将转换为unsigned int。否则,两个操作数都有   输入int。

答案 4 :(得分:0)

习惯于编译所有警告,例如gcc:

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

在您的情况下,标志-Wextra会给出以下消息:

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

这不能解释原因,但它至少会警告你;)。

解释是,与关系运算符进行比较时,评估为-1的带符号变量等于对UINT_MAX的无符号求值。

编译器必须在这种情况下做一些很好的定义,这就是人们提出的......

答案 5 :(得分:0)

当编译器看到将unsigned int与signed int进行比较时,它将signed int提升为unsigned,这意味着将此(在linux框中)添加到已签名的int:

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

所以现在你将 UINT_MAX - 1(UINT_MAX + y) x 进行比较,这清楚地解释了输出。

编辑:更清楚:在32位机器上---&gt; UINT_MAX = 2 147 483 648 = 2**31

问候。