【发布时间】:2009-06-18 01:18:11
【问题描述】:
在下面的代码块中,7 的 if 语句中发生的隐式转换是什么?我会认为它最终会是 (0x98
char minstogo = 0x98;
if(minstogo <= 7) {
DoMyStuff();
}
【问题讨论】:
标签: c
在下面的代码块中,7 的 if 语句中发生的隐式转换是什么?我会认为它最终会是 (0x98
char minstogo = 0x98;
if(minstogo <= 7) {
DoMyStuff();
}
【问题讨论】:
标签: c
Whenever you have a binary operator (one of + - * / % << >> & | ^ == != @987654333 @<=>>=) 两个不同类型的整型操作数之间,在运算前将两种类型转换为通用类型。决定转换为类型的规则是(来自 C99 标准的第 6.3.1.8 节):
如果两个操作数的类型相同,则不需要进一步转换。
否则,如果两个操作数都具有有符号整数类型或都具有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。
否则,如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数的类型的等级,然后操作数与 有符号整数类型转换为无符号操作数的类型 整数类型。
否则,如果带符号整数类型的操作数的类型可以表示 无符号整数类型的操作数类型的所有值,然后 将无符号整数类型的操作数转换为 带符号整数类型的操作数。
否则,两个操作数都转换为无符号整数类型 对应于带符号整数类型的操作数的类型。
在这种情况下,char 可以是有符号或无符号整数类型——它的符号是实现定义的。不过幸运的是,int 可以表示char 的所有可能值,无论char 是否已签名,假设您在一个chars 为8 位且ints 为至少 16 位。
如果char是有符号的,那么上面的第二段适用,所以两个操作数都被转换为int(等级更高的类型;等级的定义有点复杂,但它本质上相当于位大小类型)。由于 0x98 作为有符号的char 为负数,因此将其转换为整数 -104,即小于 7。
如果 char 是无符号的,则适用第四段。未签名的char 将转换为 152 作为int,大于 7。
永远不要依赖chars 被签名或未签名。如果您需要某种符号的 8 位整数,显式使用 signed char 或 unsigned char,或使用 C99 类型 int8_t 和 uint8_t,定义 int <stdint.h>。
很容易被整数提升规则引起的细微错误所困扰。我强烈建议您始终使用带有 gcc 的-Wall 进行编译,这会警告您有符号和无符号整数之间的比较,这通常会导致错误。
【讨论】:
这里可能发生的是 char 是有符号值,因此 0x98 注册为负数。因此它小于 7
同样在这种情况下,7 将不会进行任何转换。相反,char 将扩大到与 7 相同的整数类型,然后进行比较。
【讨论】:
将 chars 表示为 8 位字节,将 minstogo 设置为 0x98 是二进制值 10011000。符号位已设置,它是一个负整数值。您可能需要一个 unsigned char 以便测试评估为 false。
【讨论】:
它将与0x98 <= 7 评估相同,除非平台的char 类型默认为带符号且CHAR_BIT 为8。在这种情况下,minstogo 的值将为负,minstogo <= 7 将为真。
【讨论】:
【讨论】:
使用具有当前设置的编译器,char 是有符号类型:并且由于设置了其值的高位 (0x80),因此该值是负数。当 minstogo 被加宽时,该负号被保留(通过符号扩展),因此 minstogo 被加宽为小于 7 的负整数(例如 0xFF98)。
【讨论】:
-fsigned-char/-funsigned-char 开关来覆盖平台默认值。可移植代码不应依赖于 char 的(未)签名。