2016-11-11 20 views
2

Следующая программа компилируется успешно, но когда я ее запускал, она ничего не печатает, когда я инициализирую цикл for с помощью -1, но когда я инициализирую цикл с 0, он успешно проходит весь массив. Я хочу спросить, не можем ли мы сделать это пересечь массив, когда мы инициализируем цикл for с отрицательным значением?Может ли кто-нибудь объяснить, почему следующая программа ничего не выводит?

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

[Почему (sizeof (int)> -1) false?] (Http://stackoverflow.com/q/34151309/995714), [Почему -1> sizeof (int)?] (Http://stackoverflow.com/q/3100365/995714) –

ответ

2

В результате sizeof оператора имеет тип size_t, который представляет собой тип без знака.

В результате тип TOTAL_ELEMENTS также неподписан. Когда -1 сравнивается с ним, он преобразуется в большое число без знака. Вот почему d <= (TOTAL_ELEMENTS - 2) является ложным.

0

sizeof дает результат size_t, который является неподписанным. Сравните подписанный и неподписанный тип, и вы можете только ожидать, что все взорвется.

Чтобы разработать, когда вы пытаетесь использовать как подписанный, так и неподписанный тип в арифметических операциях, подписанный тип будет повышен до типа без знака, производя огромный номер. Таким образом, значение d, повышенное до неподписанного типа, не будет соответствовать условию d <= (TOTAL_ELEMENTS - 2);, поэтому тело цикла не будет выполнено.

Для операторов, ожидающих, что операнды арифметического типа вызывают преобразования. Этот шаблон называется обычным арифметическим преобразованием. для данного конкретного случая, цитируя стандарт, глава §6.3.1.8

В противном случае целые промоакции выполняются в обоих операндах. Тогда следующих правила применяются к рекламируемым операндам:

[...]

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

и относительно ранга,

  • Ранга любого целого числа без знака типа должен равняться рангом соответствующего подписанного целого типа, если таковые имеются.

Кроме того, для справки, со ссылкой на C11, глава 7.19, (курсив мой )

size_t

, который является целым числом без знака тип результата оператора SizeOf;

Подсказка: Включите предупреждение компилятора, и оно укажет на вашу ошибку.

1

Это не делает то, что вы думаете, он делает:

d <= (TOTAL_ELEMENTS - 2) 

Вместо этого:

d <= int(TOTAL_ELEMENTS - 2) 

В противном случае у вас есть подписанная-против-беззнаковое сравнение, а ваш - 1 становится максимально возможным size_t.

1

Здесь d <= (TOTAL_ELEMENTS - 2) операнды являются субъектами обычных арифметических преобразований (6.3.1.8). И на самом деле целое продвижение правила действуют в вашем случае:

  1. Если оба операнда имеют один и тот же тип, то никаких дальнейших преобразований не является необходимо.

  2. В противном случае, если оба операнда подписали целочисленные типы или оба беззнаковых целых типов, операнд с типом меньшего ранга преобразования целочисленного преобразуется к типу операнда с большего ранга.

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

  4. В противном случае, если тип операнда с подписью целочисленного типа может представлять все значений типа операнда с целым числом без знака типа, то операнда с целым числом без знака типа преобразуется к типу операнд со знаком целого типа.

  5. В противном случае оба операнда преобразуются в целое число без знака, соответствующее типу операнд со знаком целочисленного типа.

Согласно тому, что вы получили ваш код попадает в пункте № 3, то ваш подписал -1 преобразовывается с помощью правила (6.3.1.3):

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

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