2010-08-01 2 views
3

Ожидаемый вывод следующей программы на C предназначен для печати элементов массива. Но когда он действительно работает, он этого не делает.Элементы массива печати

#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; 
} 

В чем причина?

+0

Почему не просто 'для (d = 0; d fredoverflow

+2

Возможно, это поучительный пример того, насколько сложно правильно программировать на C. И в связи с этим это действительно очень хороший пример. –

+0

Этот вопрос является частью [головоломки Gowri Korumar's C] (http://www.gowrikumar.com/c/), сборник из 50 очень учебных вопросов C. Я ответил на первые 25 вопросов как от прошлых знаний, так и от исследований, в случае, если это помогает: [C головоломки ответил] (http://codeitdown.com/c-puzzles-answered/). – JoseV

ответ

5

Выполнение сравнения d <= (TOTAL_ELEMENTS-2), тип преобразования. d имеет тип signed int, а (TOTAL_ELEMENTS-2) имеет тип size_t, который является неподписанным. Правила C говорят, что когда оператор имеет подписанный и неподписанный аргумент, а аргумент unsigned имеет больший или равный размер для подписанного аргумента, то подписанный аргумент преобразуется в unsigned.

То есть, сравнение заканчивается как:

(size_t) d <= (TOTAL_ELEMENTS-2) 

И потому size_t беззнаковым, (size_t) -1 действительно, на самом деле большое количество, а не -1 больше. Для 32-битного size_t это будет 2 - 1 = 4 294 967 295.

Чтобы это исправить, вы можете явно привести правую подписанному INT:

d <= (int) (TOTAL_ELEMENTS-2) 

Или, лучше, просто избавиться от странной отрицательной индексации и тому подобное.

Для справок в будущем, включите все предупреждения компилятора вы можете. НКА, например, будет выдавать предупреждение, если вы включите -Wall -Wextra:

$ gcc -o arrayprint -Wall -Wextra -ansi arrayprint.c 
arrayprint.c: In function ‘main’: 
arrayprint.c:11: warning: comparison between signed and unsigned 
+0

, за исключением того, что результат макроса превратился в 'int', было бы гораздо проще использовать' size_t' для 'd' с самого начала и использовать правильные границы' 0' для начала и 'd

6

TOTAL_ELEMENTS неподписан. -1, при преобразовании в unsigned, является действительно огромным числом, которое не меньше 6. Таким образом, ваш цикл никогда не запускается.

+0

Да ... вы никогда не должны смешивать подписанные/неподписанные задания или сопоставление без надлежащей причины, и в этом случае явное кастинг на месте. Кроме того, большинство компиляторов должны были выдать предупреждение для этого, если был установлен соответствующий уровень предупреждения. – smichak

1

Причина в том, что цикл никогда не выполняется. Это связано с тем, что TOTAL_ELEMENTS возвращает size_t, неподписанный тип.

Вы можете исправить это путем литья (TOTAL_ELEMENTS-2) в инт.

0

Вам нужно сделать следующее:

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

, как sizeof(...) производит значение без знака.

3

В первом, я не знаю. Но когда я собирал его с помощью GCC, это было очевидно, очевидно:

$ gcc -Wall -Wextra -Os a.c 
a.c: In function `main': 
a.c:11: warning: comparison between signed and unsigned 

Так у вас есть сравнение следующим образом:

(int) -1 <= (size_t) 5 

Поскольку один из типов подписан, а другой без знака, они первые необходимо преобразовать в общий тип. В этом случае это size_t. Это делает его:

(size_t) -1 <= (size_t) 5 

Теперь -1 не может быть представлен в беззнаковом типе.Таким образом, 2^32 (или сколько бит size_t имеет) добавляется к нему, что делает его 4294967295. Так что сравнение на самом деле:

4294967295 <= 5 

И это false, поэтому тело цикла никогда не выполняется.

0

Просто измените

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

С

#define TOTAL_ELEMENTS (int)(sizeof(array)/sizeof(array[0]))-2 
+0

вы действительно воспринимаете это неправильно. Индексы массивов всегда должны быть просто 'size_t'. Он просто должен изменить 'd' на' size_t' и сделать правильную индексацию, и весь пух уходит ... –

Смежные вопросы