我不懂这个!
#include <stdio.h>
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&amp; 4.2
答案 0 :(得分:13)
我不确定,但我怀疑表达式t2-1会自动扩展为int值。 我这里没有c标准确切的转换规则是什么,但我相信小于int的类型会自动加宽。
答案 1 :(得分:12)
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
部分最终为负数。
在表达式中:
s1 < s2-1
unsigned long
类型未被提升,因为它们的排名高于int
/ unsigned int
,因此表达式使用无符号算术进行评估(带有下溢值)减法),s2-1
子表达式的计算结果非常大,而不是负数。
如评论中指出的那样,如果平台的int
实现为16位类型(例如允许 - 例如MS-DOS),则unsigned short
的促销将是{ {1}}代替unsigned int
,因为int
无法表示int
的所有值(unsigned short
必须至少为16位)。在这种情况下,两个unsigned short
语句都将评估为true。
答案 2 :(得分:3)
t2
是u16,1
是int
(大概是32位),所以t2-1
就是这种“不同类型之间的操作”并导致对int的整体强制(因为它比你的“更长”......)。后来,由于s2和1都是32位(虽然具有不同的符号),但整体强制是无符号长。因此,所涉及的类型的大小确实有助于确定整体强制的签名。
我建议避免使用混合签名(理想情况下也是混合大小!)操作(通过强制转换或特殊字面符号表示文字,例如1
,否则会int
类型并使你的生活更具潜力复杂且您的代码可能无法移植; - )。
答案 3 :(得分:0)
-1表示为全1。因此,当解释为无符号时,其值为2 ^ 32-1,这显然大于0.我猜第一个比较是扩展到执行32位带符号算术(可能是因为“1”是一个签署int)。
请注意,以下将转到printf,因为现在再次在16位无符号空间中进行比较:
u32 temp = t2 - 1;
if( t1 < temp )
printf(" t1 < t2-1\n");