Почему это происходит с оператором sizeof при сравнении с отрицательным числом?

Что на самом деле происходит здесь? Выход теперь «False»:

#include  int main() { if (sizeof(int) > any_negative_integer) printf("True"); else printf("False"); return 0; } 

Если я изменю его на:

 if (sizeof(int) < any_negative_integer) 

выход «True».

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

sizeof возвращает size_t без знака и поэтому -1 преобразуется в очень большое беззнаковое число. Использование правильного уровня предупреждения помогло бы здесь, -Wconversion с помощью -Wconversion или -Weverything ( обратите внимание, что это не для использования в производстве ) флаги предупреждают нас:

 warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion] if (sizeof(int) > -1) ~ ^~ 

Для gcc вы получаете аналогичное предупреждение, используя флаг -Wextra :

 warning: comparison between signed and unsigned integer expressions [-Wsign-compare] if (sizeof(int) > -1) ^ 

Для справки мы знаем, что size_t не имеет знака из стандартного раздела проекта C99 7.17 Общие определения, которые гласят:

  size_t 

который представляет собой целочисленный тип без знака результата оператора sizeof, […]

Обратите внимание: в этом случае не указано ничего другого, в моем конкретном случае это будет unsigned long, но это не обязательно.

Преобразование -1 связано с обычным арифметическим преобразованием, 6.3.1.8 в разделе 6.3.1.8 Обычные арифметические преобразования, которые гласят:

[…]

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

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

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

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

Почему -1 заканчивается большим значением без знака, на самом деле он заканчивается тем, что является максимальным значением неподписанного типа, из-за раздела 6.3.1.3 Целочисленные и беззнаковые целые числа, которые гласят:

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

Таким образом, мы получаем:

 -1 + (UMAX + 1) 

который:

 UMAX 

и таким образом заканчиваются:

 if (sizeof(int) > UMAX ) 

Поскольку sizeof() возвращает size_t , неподписанный тип. Сравнение типов подписи и без знака может дать неожиданные результаты из-за неявного литья перед сравнением.

  • Использование GhostScript для получения размера страницы
  • Почему расчетная ширина и высота в пикселе строки в Tkinter различаются между платформами?
  • Как работает эта функция шаблона «размер массива»?
  • resize массива
  • Выбор размера System.Drawing.Icon?
  • Загрузить значение измерения из res / values ​​/ dimension.xml из исходного кода
  • Является ли sizeof (некоторый указатель) всегда равным четырем?
  • Сколько данных может содержать список максимум?
  • где найти значение XSS по умолчанию для Sun / Oracle JVM?
  • Как resize шрифта JLabel, чтобы взять максимальный размер
  • Java / ImageIO получает размеры изображения без чтения всего файла?
  • Давайте будем гением компьютера.