为什么这两个程序在ANSI C中表现不同?

时间:2009-02-01 06:05:54

标签: c

  

可能重复:
  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。 他们为什么表现不同?

3 个答案:

答案 0 :(得分:4)

对于第一个,右侧是unsigned char,并且所有unsigned char值都符合signed int,因此它将转换为signed int。

对于第二个,右侧是unsigned int,因此左侧从signed int转换为unsigned int。

另见this CERT document on integer conversions

答案 1 :(得分:1)

starblue解释了你问题的第一部分。我将采取第二部分。因为TOTAL_ELEMENTSsize_t,它是无符号的,所以int被转换为无符号类型。你的size_t是这样的,int不能代表它的所有值,所以intsize_t的转换发生了,而不是size_tint

将负数转换为无符号是完全定义的:值包围。如果您将-1转换为unsigned int,则会以UINT_MAX结尾。无论你是否使用二进制补码来表示负数,都是如此。

rationale for C文档提供了有关值保留转换的更多信息。

答案 2 :(得分:0)

以下是我记得如何应用自动转换的方式:

  • 如果操作数大小不同,则转换应用于较小的操作数,使其与较大的操作数类型相同(如果较小的操作数已签名,则带符号扩展名)

  • 如果操作数大小相同,但是一个是有符号的而另一个是无符号的,那么带符号的操作数将转换为无符号

虽然上述情况可能不适用于所有实现,但我认为它对所有二进制补码实现都是正确的。