可能重复:
A riddle (in C)
1
main()
{
if(-1<(unsigned char)1)
printf("-1 is less than (unsigned char)1:ANSI semantics");
else
printf("-1 NOT less than (unsigned char)1:K&R semantics");
}
2
int array[] = {23,41,12,24,52,11};
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))
main()
{
int d = -1,x;
if(d<=TOTAL_ELEMENTS -2)
x = array[d+1];
}
第一个将unsigned char 1转换为ANSI C中的signed签名变量, 而第二个程序将d转换为无符号的int,使得 条件表达式在ANSI C中返回false。 他们为什么表现不同?
答案 0 :(得分:4)
对于第一个,右侧是unsigned char,并且所有unsigned char值都符合signed int,因此它将转换为signed int。
对于第二个,右侧是unsigned int,因此左侧从signed int转换为unsigned int。
答案 1 :(得分:1)
TOTAL_ELEMENTS
是size_t
,它是无符号的,所以int被转换为无符号类型。你的size_t是这样的,int不能代表它的所有值,所以int
到size_t
的转换发生了,而不是size_t
到int
。
将负数转换为无符号是完全定义的:值包围。如果您将-1
转换为unsigned int
,则会以UINT_MAX
结尾。无论你是否使用二进制补码来表示负数,都是如此。
rationale for C文档提供了有关值保留转换的更多信息。
答案 2 :(得分:0)
以下是我记得如何应用自动转换的方式:
如果操作数大小不同,则转换应用于较小的操作数,使其与较大的操作数类型相同(如果较小的操作数已签名,则带符号扩展名)
如果操作数大小相同,但是一个是有符号的而另一个是无符号的,那么带符号的操作数将转换为无符号
虽然上述情况可能不适用于所有实现,但我认为它对所有二进制补码实现都是正确的。