Подтвердить что ты не робот

Оператор sizeof() в if-statement

#include <stdio.h>
int main(void)
{
    if (sizeof(int) > -1)
        printf("True");
    else
        printf("False");
}

Это печатает False. Почему sizeof() не возвращает значение в if?

4b9b3361

Ответ 1

  • sizeof не является функцией, это оператор. Скобки не являются частью имени оператора.
  • Это не так, потому что генерируемое значение имеет неподписанный тип size_t, что приводит к "обычным арифметическим преобразованиям", в которых -1 преобразуется в unsigned, и в этом случае это очень большое число.

В основном вы сравниваете 4 > 0xffffffffu, или что-то близкое к этому, по крайней мере. Подробнее см. этот вопрос.

Ответ 2

Неподписанное и подписанное целочисленное продвижение (точнее, "обычные арифметические преобразования" ). sizeof дает значение типа size_t, и по сравнению с беззнаковым значением (которое size_t есть), -1 продвигается к этому типу и переполняется и становится огромным.

Незнакомое целочисленное переполнение имеет четко определенное поведение и должно приниматься как modulo 2 ^ width, где width - это количество бит в конкретном неподписанном целочисленном типе. Итак, если у вас есть 32-разрядная ширина size_t и int, например, ваше сравнение будет эквивалентно с

if (4 > 4294967295u)

что, очевидно, неверно.

Ответ 3

  • Операнды операторa > в выражении if: sizeof(int) и -1.
  • sizeof(int) имеет тип size_t, который гарантированно является целым числом без знака. На практике size_t, скорее всего, будет как минимум равным unsigned int для любой системы.
  • -1 имеет тип int, что эквивалентно signed int.
  • Не происходит никаких целых рекламных акций, так как оба операнда имеют достаточно большие целые типы.
  • Затем два операнда сбалансированы в соответствии с правилом C, формально называемым обычными арифметическими преобразованиями.

Это состояние (C11 6.3.1.8):

...

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

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

  • Последнее из вышесказанного произойдет, поскольку (подписанный) int не может соответствовать всем значениям a size_t.
  • Таким образом, -1 преобразуется в целое число без знака. На практике size_t скорее всего эквивалентен либо unsigned int, либо unsigned long. Что бы ни случилось, когда вы сохраняете -1 в такой переменной, это поведение, определяемое реализацией.
  • На двухкомпонентном компьютере (99,9% всех компьютеров в мире) -1 будет интерпретироваться как 0xFFFFFFFF (количество FF зависит от размера int в данной системе).
  • 4 > 0xFFFFFFFF оценивается как false.

Ответ 4

Sizeof - это оператор, который приводит к длинному int без знака. Следовательно, при сравнении unsigned long int с -1, который хранится как 0xffffffff (размер int равен 4 байтам).

-1 по умолчанию является целым знаком. Но, в сравнении между подписанным int и unsigned int, компилятор идет с неявным typecasting подписанного int в unsigned int. Это приводит к тому, что unsigned -1 будет приблизительно равным 4.6giga-значению.

Следовательно, выход false.

Ответ 5

Просто проверьте это и убедитесь сами.

#include <stdio.h>
main() {
    unsigned int a=4;
    int b = -1;
    //this is what you're doing
    printf("%u vs %u\n", a, (unsigned int)b);
    //this is what you want to do instead
    printf("%d vs %d\n", (int)a, b);
}