Загадка (в 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]);
getchar();
return 0;
}
Вышеприведенный код должен печатать все элементы массива, в чем проблема в коде (вывод ничего)? Я думаю, что цикл не повторяется еще раз?
Я узнал, что работает следующий код :
#include<stdio.h>
#define TOTAL_ELEMENTS ((sizeof(array) / sizeof(array[0])))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
int x = (TOTAL_ELEMENTS-2);
for(d=-1;d <= x;d++)
printf("%d\n",array[d+1]);
getchar();
return 0;
}
У меня есть теория, что это как-то связано с макросом, но я не могу сказать о проблеме.
Ответы
Ответ 1
Проблема заключается в том, что (TOTAL_ELEMENTS-2)
- это значение без знака. Когда вы делаете сравнение d <= (TOTAL_ELEMENTS-2)
, оба значения преобразуются в значения без знака, а результат - false.
В вашем втором примере x
подписан, поэтому нет проблем.
Ответ 2
Оператор sizeof
дает результат типа size_t
. В первой версии вы сравниваете int
(подписанный) с size_t
(без знака).
Во второй версии вы преобразуете выражение size_t
в int
, назначив его, и, следовательно, оба операнда сравнения имеют один и тот же тип.
Ответ 3
Еще один способ увидеть эту проблему следующим образом
#include<stdio.h>
int main() {
int i = -5;
unsigned int j = 6;
if(i < j)
printf("-5 is less than 6");
else
printf("-5 is greater than 6");
return 0;
}
Выход:
-5 is greater than 6
Причина: Сравнение беззнакового целого с целым числом со знаком всегда будет возвращать false.
В вопросительном случае sizeof возвращает неподписанный тип данных, но он сравнивается с типом подписан (- это ошибка)
Ответ 4
Я запускаю следующую программу без использования макроса, и вывод ничего не был
#include<stdio.h>
int main()
{
int d;
for(d=-1;d<=sizeof(int);d++)
{
printf("sizeof operator\n");
}
return 0;
}
Итак, это означает, что проблема не в MACRO, а в типе значения sizeof возвращается. sizeof возвращает размер типа данных как size_t без знака, но -1 неявно преобразуется в unsigned, который равен 0xffffffff и, очевидно, больше sizeof (int).
Также посмотрите Пример несоответствующего кода (сравнение)