【问题标题】:Signed/unsigned mismatch compare有符号/无符号不匹配比较
【发布时间】:2020-09-18 04:03:36
【问题描述】:
#include <stdio.h>
int main()
{
    int a = -2;         // 0xFFFFFFFE
    unsigned int b = 1; // 0x00000001

    if ((int)a > (int)b) printf("(int)a > (int)b;\n");
    else printf("(int)a < (int)b;\n");

    if ((unsigned int)a > (unsigned int)b) printf("(unsigned int)a > (unsigned int)b;\n");
    else printf("(unsigned int)a < (unsigned int)b;\n");

    if (a > b) printf("a > b;\n");
    else printf("a < b;\n");

    char c = -2;         // 0xFE
    unsigned char d = 1; // 0x01

    if ((char)c > (char)b) printf("(char)c > (char)d;\n");
    else printf("(char)c < (char)d;\n");

    if ((unsigned char)c > (unsigned char)d) printf("(unsigned char)c > (unsigned char)d;\n");
    else printf("(unsigned char)c < (unsigned char)d;\n");

    if (c > d) printf("c > d;\n");
    else printf("c < d;\n");

    return 0;
}


run result is:
(int)a < (int)b;
(unsigned int)a > (unsigned int)b;
a > b;
(char)c < (char)d;
(unsigned char)c > (unsigned char)d;
c < d;

为什么是 a>bc?什么是默认的编译器标尺? 我最初认为编译器会将所有数字转换为 int 类型,但这让我感到困惑。

【问题讨论】:

  • int a = -2; // 0xFFFFFFFE 中的评论具有误导性。 a 可能具有 0xFFFFFFFE 的位模式,但它仍然具有 -2 的 。如果 int 是 32、16、64 或 42 位,则它具有该值。如果用 2 的补码、1 的补码或符号幅度编码,则它具有该值。它没有 0xFFFFFFFE (4,294,967,294) 的值。 &gt; 取决于值,而不是位模式或编码。

标签: c unsigned signed


【解决方案1】:

为什么a>b

当相同等级的两种类型(根据需要通常提升到int/unsigned之后)但符号不同时,将有符号类型转换为无符号类型。

int a = -2;
unsigned int b = 1;
if (a > b)
if ((unsigned)a > b)   // convert int to unsigned
if ((unsigned)-1 > 2)  // convert int to unsigned
if (UINT_MAX > 2)

为什么要c

int/unsigned 给定的char 的通常促销活动是签名 char

char c = -2;        
unsigned char d = 1;
if ((int)c > (int)d)  // promote char to int
if ((int)-2 > (int)1)
if (-2 > 1)

char 曾是一个未签名 char

char c = -2; // c takes on the value of CHAR_MAX + 1 - 2 (254)
char c = 254;        
unsigned char d = 1;
if ((int)c > (int)d)  // promote char to int
if ((int)254 > (int)1)
if (254 > 1)

【讨论】:

    【解决方案2】:

    这遵循 Usual arithmetic conversions 的 C 规则。

    关系运算符 、=、==、!=
    ...
    4) 否则,两个操作数都是整数。两个操作数都经过整数提升(见下文);然后,在整数提升之后,以下情况之一适用: 如果类型相同,则该类型为通用类型。

    否则(类型不相同):如果类型具有相同的符号(有符号或无符号),则类型具有较小转换等级(见下文)的操作数将隐式转换为其他类型。

    否则(有符号不同):如果无符号类型的转换等级大于或等于有符号类型的等级,则有符号类型的操作数被隐式转换为无符号类型.

    否则(有符号不同,无符号类型的转换秩小于有符号类型):如果有符号类型可以表示无符号类型的所有值,则无符号类型的操作数隐式转换为有符号类型输入。

    否则:两个操作数都会隐式转换为有符号操作数类型的对应无符号类型。

    例如a &gt; b 的情况在上面突出显示:操作数具有相同的int 类型,但符号不同。 int 不涵盖 unsigned int 值的整个范围(在通常的实现中,大概包括 OP),因此 unsigned 类型具有比 int 更高的转换等级和比较以(unsigned)a &gt; b 完成。其他情况遵循相同的规则。

    【讨论】:

      【解决方案3】:

      由于“通常的算术转换”,signed int 将在比较之前转换为 unsigned int

      更多关于“通常的算术转换”:C in a Nutshell

      否则,一个操作数有一个有符号类型 T,其转换等级为 高于其他操作数的类型。另一个操作数是 仅当类型 T 能够表示所有 其先前类型的值。如果不是,则转换两个操作数 对应有符号类型T的无符号类型。

      以下代码行包含一些示例:

      int i = -1;
      unsigned int limit = 200U;
      long n = 30L;
      
      if ( i < limit )
        x = limit * n;
      

      在此示例中,要评估 if 条件中的比较,必须首先将 i 的值 -1 转换为 输入无符号整数。结果是一个很大的正数。在 32 位 系统,这个数字是 2^32 - 1,并且在任何系统上它都大于 limit。因此,if 条件为假。

      【讨论】:

        猜你喜欢
        • 2011-07-21
        • 2012-10-02
        • 1970-01-01
        • 2016-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-28
        相关资源
        最近更新 更多