Цикл, начинающийся с -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 ответа:
sizeof
возвращает целое число без знака, поэтомуTOTAL_ELEMENTS
тоже без знака.это. Изначально,
d
и-1
. Однако, при выполнении сравнения,d
неявно типизируется в unsigned, поэтому он больше не-1
при сравнении сTOTAL_ELEMENTS
, это на самом делеUINT_MAX
(т. е.4294967295
на моей машине, но могут отличаться для других).и
если вы хотите исправить это, typecast
TOTAL_ELEMENTS
toint
: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
at0
и бегите кTOTAL_ELEMENTS - 1
вместо? Вы даже можете отбросить typecast, что необходимо только для углового случаяd = -1
.for(d = 0; d < TOTAL_ELEMENTS; d++) printf("%d\n", array[d]);
в качестве сноски, вот соответствующие стандартные выдержки C99:
6.3.1.8p2 определяет преобразование из signed в unsigned тип.
если операнд с целочисленным типом без знака имеет ранг, больший или равный рангу типа другого операнда, то операнд со знаком целочисленного типа преобразуется в тип операнда с беззнаковый целочисленный тип.
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.