2017-08-13 174 views
51

该程序应打印出array的元素,但运行时不显示输出。从-1开始的循环不打印任何东西

#include <stdio.h> 

#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0])) 

int array[] = { 23, 34, 12, 17, 204, 99, 16 }; 

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

为什么没有这个计划表现出任何输出?

+37

用硬编码的变量名宏是自找麻烦。 – jackarms

+1

更改字符'D = 0'做输出的东西虽然 –

+1

@TonyTannous但它没有解释什么是在OP – CIsForCookies

回答

145

sizeof返回一个无符号整数,所以TOTAL_ELEMENTS也是无符号的。

d已签名。起初,d-1。但是,这样做比较时,d被隐式类型强制转换为无符号,因此它不再-1被比较TOTAL_ELEMENTS时,它实际上是UINT_MAX(这是4294967295我的机器上,但可能会为其他人的不同)。

此外,

如果要解决这个问题,强制转换TOTAL_ELEMENTSint

for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++) 

这将打印:

23 
34 
12 
17 
204 
99 
16 

正如你所期望。您可能还想查看Comparison operation on unsigned and signed integers以获取有关signed-unsigned比较主题的更多信息。

值得注意的是开启编译器警告就已经帮助你弄清楚发生了什么事情(如海德在他comment观察):

$ gcc -Wall -Wextra test.c 
test.c:7:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] 
     for(d = 0; d < TOTAL_ELEMENTS; d++) 
       ~^~~~~~~~~~~~~~~ 
1 warning generated. 

或者,为什么不开始d0并运行到TOTAL_ELEMENTS - 1而不是?您甚至可以删除类型转换,仅在d = -1的情况下才需要。

for(d = 0; d < TOTAL_ELEMENTS; d++) 
    printf("%d\n", array[d]); 

作为一个注脚,这里有相关的C99标准摘录:

  1. 6.3.1.8p2从符号到无符号类型定义的转换。

    如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,然后 用符号整型操作数被转换为 操作数与无符号整数的类型类型。

  2. 6.3.1.3p2定义转换是如何完成的:通过添加UINT_MAX + 1的符号表示。

    如果新类型是无符号的,则该值是通过重复地加上或减去小于能够在新的类型来表示,直到该值是在 范围的新类型的最大值 多一个转换。

    所以-1 =>-1 + (UINT_MAX + 1) = UINT_MAX,对于这种情况。

35

我的gcc的输出这样的警告:

warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] 
     for(d = 0; d < TOTAL_ELEMENTS; d++) 

这意味着(TOTAL_ELEMENTS-2)unsigned intdsigned int。这使得总的表达为falsed的初始值,因为(unsigned int)(-1) > (TOTAL_ELEMENTS-2)。不同的积分类型之间

+19

是的。教训:始终启用所有警告并读取它们 –

+1

表达式不是*总是false *,它对于'd'的初始值是错误的。 – chqrlie

4

二进制操作由所谓的通常的算术转换定义的“公共”型内进行。所以int d是用值-1初始化的单类型。其中,当转换为unsigned int类型,它将返回最大unsigned int类型,其比 TOTAL_ELEMENTS返回的值多少要大得多。

+1

答案中的'unsigned int'应该是'size_t'。除此之外,你是在谈论点。 – StoryTeller