谁能解释为什么以下程序什么都不输出?

时间:2016-11-11 06:42:56

标签: c arrays sizeof unsigned signed

以下程序编译成功但是当我运行它时,它在我用-1初始化for循环时没有打印,但是当我用0初始化循环时它成功遍历所有数组。我想问我们可以不要&# 39;当我们用负值??

初始化for循环时,t遍历数组
#include <stdio.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23, 34, 12, 17, 204, 99, 16};

int main(void) {
    int d;
    //printf("%d",TOTAL_ELEMENTS);
    for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++) 
    {
        printf("%d ",d);
        printf("%d\n", array[d+1]);
    }    
    return 0;
}

4 个答案:

答案 0 :(得分:2)

sizeof运算符的结果是size_t类型,这是一种无符号类型。

因此,TOTAL_ELEMENTS的类型也是无符号的。将-1与之进行比较时,会将其转换为无符号数。这就是为什么d <= (TOTAL_ELEMENTS - 2)是错误的。

答案 1 :(得分:1)

这不符合你的想法:

d <= (TOTAL_ELEMENTS - 2)

相反,这样做:

d <= int(TOTAL_ELEMENTS - 2)

否则你的签名与未签名比较,你的-1成为最大的size_t

答案 2 :(得分:1)

此处d <= (TOTAL_ELEMENTS - 2)个操作数是通常的算术转换(6.3.1.8)的主题。实际上,整数促销规则适用于您的情况:

  
      
  1. 如果两个操作数具有相同的类型,则不再进一步转换   需要的。

  2.   
  3. 否则,如果两个操作数都有有符号整数类型或两者都有   有无符号整数类型,操作数类型较小   整数转换等级转换为操作数的类型   更高的等级。

  4.   
  5. 否则,如果操作数具有无符号整数类型   等级大于或等于另一个等级的等级   操作数,然后将带有符号整数类型的操作数转换为   具有无符号整数类型的操作数的类型。

  6.   
  7. 否则,如果是类型   带有符号整数类型的操作数可以代表所有的   具有无符号整数类型的操作数类型的值,然后是   具有无符号整数类型的操作数转换为的类型   带有符号整数类型的操作数。

  8.   
  9. 否则,两个操作数都是   转换为对应于类型的无符号整数类型   带有符号整数类型的操作数。

  10.   

根据您所获得的代码,您的代码属于第3条,然后您的签名-1将通过规则(6.3.1.3)进行转换:

  

否则,如果新类型是无符号的,则转换为   重复加或减一个以上的最大值   可以用新类型表示,直到值在范围内   新类型。

结果它变成一个非常大的无符号值,肯定大于TOTAL_ELEMENTS - 2并且你永远不会进入循环。

答案 3 :(得分:0)

sizeof生成size_t的结果,该结果是无符号的。比较有符号和无符号类型,你只能期望事情爆发。

详细说明,当您尝试在算术运算中同时使用有符号和无符号类型时,签名类型将被提升为无符号类型,从而生成巨大数字。因此,提升为无符号类型的d的值将无法满足条件d <= (TOTAL_ELEMENTS - 2);,因此循环体将不会执行。

对于期望算术类型的操作数导致转换的运算符。这种模式称为通常的算术转换。对于这个特殊情况,引用标准,章节§6.3.1.8

  

否则,将对两个操作数执行整数提升。那么   以下规则适用于提升的操作数:

     

[...]

     
      
  • 否则,如果具有无符号整数类型的操作数的等级更大或   等于另一个操作数的类型的等级,然后是操作数   有符号整数类型转换为带有unsigned的操作数的类型   整数类型。
  •   

,关于排名

  
      
  • 任何无符号整数类型的等级应等于相应的等级   有符号整数类型,如果有的话。
  •   

另外,作为参考,引用C11,第7.19章,(强调我的

  

size_t

     

是sizeof运算符的结果的无符号整数类型;

提示:启用编译器警告,它将指向您的错误。