2017-08-13 176 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