C比较char和int

在下面的代码块中,7语句的if语句中发生的impicit转换是什么? 虽然它会最终成为(0x98 <= 0x07),但这不会发生,因为条件评估为true并且DoMyStuff被调用。

char minstogo = 0x98; if(minstogo <= 7) { DoMyStuff(); } 

每当你在两个不同类型的积分操作数之间有一个二元运算符( + - * / % << >> & | ^ == != <= >= )时,这两种类型之前会被转换为一个公共类型执行操作。 决定转换类型的规则是(来自C99标准的第6.3.1.8节):

如果两个操作数具有相同的类型,则不需要进一步的转换。

否则,如果两个操作数都具有有符号整数类型或两者都具有无符号整数类型,则具有较小整数转换等级类型的操作数将转换为具有更高等级的操作数的类型。

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

否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为带有符号整数类型的操作数的类型。

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

在这种情况下, char可以是有符号或无符号整数类型 - 其签名是实现定义的。 幸运的是, int可以表示char所有可能值,无论char是否已签名,假设您处于char为8位且int s至少为16位的系统上。

如果char被签名,则上面的第二段适用,因此两个操作数都转换为int (具有更高排名的类型; rank以稍微复杂的方式定义,但它基本上等同于类型的位大小)。 由于0x98(作为有符号的char )是负数,因此它被转换为整数-104,然后小于7。

如果char是无符号的,那么第四段适用。 unsigned char将作为int转换为152,大于7。

不要依赖签名或未签名的char 。 如果需要某个签名的8位整数,请显式使用signed charunsigned char ,或使用C99类型int8_tuint8_t ,定义为int

很容易被整数提升规则引起的细微错误所困扰。 我强烈建议你总是使用-Wall编译gcc,它会警告你有关有符号和无符号整数之间的比较,这通常是导致错误的原因。

这里可能发生的是char是一个带符号的值,因此0x98注册为负数。 因此它不到7

同样在这种情况下,7将不会转换。 相反,char将被扩展为与7相同的整数类型,然后进行比较。

将字符表示为8位字节,将minstogo设置为0x98是二进制值10011000.符号位置位,它是负整数值。 您可能需要一个unsigned char,以便测试评估为false。

它将评估相同的0x98 <= 7除非平台的char类型默认为signed并且CHAR_BIT为8.在这种情况下, minstogo的值将为负, minstogo <= 7将为真。

0x98是152。

由于您已声明了“char”,而不是“unsigned char”,因此您尝试将152分配给范围为-128 – 127的类型 。

这将溢出,并给你一个负数,它将是<7(0x07)。

使用编译器及其当前设置,char是有符号类型:并且因为设置了其值的高位(0x80),该值为负。 当minstogo被加宽时,该负号将被保留(通过符号扩展),因此minstogo被加宽为负整数(例如0xFF98),小于7。