Цикл, начинающийся с -1, ничего не печатает [дубликат]


этот вопрос уже есть ответ здесь:

  • Загадка (в C) 4 ответы
  • Что не так со следующим кодом C? [дубликат] 3 ответы
  • Запутался в расширении макроса C и целочисленной арифметике [дубликат] 4 ответы
  • Почему условие цикла " for " не выполняется? [дубликат] 5 ответов
  • Печать элементов массива 6 ответов

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

#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("%dn", array[d + 1]);
    return 0;
}

почему эта программа не показывает никаких выходных данных?

3 52

3 ответа:

sizeof возвращает целое число без знака, поэтому TOTAL_ELEMENTS тоже без знака.

это. Изначально,d и -1. Однако, при выполнении сравнения,d неявно типизируется в unsigned, поэтому он больше не -1 при сравнении с TOTAL_ELEMENTS, это на самом деле UINT_MAX (т. е. 4294967295 на моей машине, но могут отличаться для других).

и

если вы хотите исправить это, typecast TOTAL_ELEMENTS to int:

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

это будет напечатано:

23
34
12
17
204
99
16

как и следовало ожидать. Вы также можете посмотреть операция сравнения целых чисел без знака и знака для получения дополнительной информации по теме сравнения со знаком-без знака.

стоит отметить, что включение предупреждений компилятора помогло бы вам понять, что происходит (как заметил Хайд в своем комментарий):

$ 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.

в качестве альтернативы, почему бы не начать d at 0 и бегите к TOTAL_ELEMENTS - 1 вместо? Вы даже можете отбросить typecast, что необходимо только для углового случая d = -1.

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

в качестве сноски, вот соответствующие стандартные выдержки C99:

  1. 6.3.1.8p2 определяет преобразование из signed в unsigned тип.

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

  2. 6.3.1.3p2 определяет, как выполняется преобразование: путем добавления UINT_MAX + 1 к подписанному представлению.

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

    так -1=>-1 + (UINT_MAX + 1)= UINT_MAX для этого сценария.

мой 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 int пока d - это signed int. Это делает выражение всегда false для начального значения d С (unsigned int)(-1) > (TOTAL_ELEMENTS-2).

двоичные операции между различными целыми типами выполняются в рамках "общего" типа, определяемого так называемыми обычными арифметическими преобразованиями. Таким образом, int d имеет опаленный тип, инициализированный значением -1. Который при преобразовании в unsigned int он вернет максимум unsigned int, который намного больше, чем значение, возвращаемое TOTAL_ELEMENTS.