unsigned long 0 <-1?
我不懂这个!
#include int main() { unsigned short t1 = 0, t2 = 0; if( t1 < t2-1 ) printf(" t1 < t2-1\n"); unsigned long s1 = 0, s2 = 0; if( s1 < s2-1 ) printf(" s1 < s2-1\n"); }
这会导致:
s1 < s2-1
要么两者都失败,要么两者都失败。 我用gcc 4和4.2试过这个
C语言为许多操作员执行“常用算术转换” – 转换在C99标准的6.3.1.8中概述。 对于整体操作数,会执行首次促销,这就是造成问题的原因。 6.3.1.1(算术操作数/布尔值,字符和整数)概述了这些促销,其中包括:
如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int。 这些被称为整数促销。 整数促销不会更改所有其他类型。
促销仅应用于具有小于int
和unsigned int
(或位域)的整数类型的对象或表达式。
所以在你的经历中:
t1 < t2-1
即使变量是unsigned short
它们也会被提升为int,因为在你的平台上int
可以表示unsigned short
所有值。 因此,使用int
类型计算表达式,并且不会发生下溢 - 表达式的t2-1
部分最终为负1。
在表达式中:
s1 < s2-1
unsigned long
类型不会被提升,因为它们具有比int
/ unsigned int
更高的'rank',所以使用无符号算术(使用减法的下溢)来s2-1
表达式,并且s2-1
子表达式求值为非常数量多,不是负数1。
正如litb在评论中指出的那样,如果平台将int
实现为16位类型(例如允许 - 例如MS-DOS),则unsigned short
的提升将是unsigned int
而不是int
,因为int
wouldn' t能够表示unsigned short
所有值( unsigned short
必须至少为16位)。 在这种情况下,两个if
语句都将评估为true。
我不确定,但我怀疑表达式t2-1自动扩展为int值。 我这里没有c标准确切的转换规则是什么,但我相信小于int的类型会自动加宽。
正如您所发现的那样,只要您在不同类型之间操作,C强制并不总是显而易见的。 t2
是u16,1是int
(大概是32位),所以t2-1
正是这种“不同类型之间的操作”并导致对int的整体强制(因为它比u16 ……“更长”)。 之后,由于s2和1都是32位(虽然具有不同的符号),因此整体强制为无符号长。 因此,所涉及的类型的大小确实有助于确定整体强制的签名。
我建议避免使用混合签名(理想情况下也是混合大小!)操作(通过强制转换或特殊文字符号表示文字,例如1
,否则将具有int
类型并使您的生活变得复杂并且您的代码可能无法移植;-)。
-1表示为全1。 因此,当解释为无符号时,其值为2 ^ 32-1,这显然大于0.我猜第一个比较是扩展到执行32位有符号算术(可能是因为“1”是一个签名int)。
请注意,以下将转到printf,因为现在再次在16位无符号空间中进行比较:
u32 temp = t2 - 1; if( t1 < temp ) printf(" t1 < t2-1\n");