#include <stdio.h>
int main(void)
{
if (sizeof(int) > -1)
printf("True");
else
printf("False");
}
Это печатает False
. Почему sizeof() не возвращает значение в if
?
#include <stdio.h>
int main(void)
{
if (sizeof(int) > -1)
printf("True");
else
printf("False");
}
Это печатает False
. Почему sizeof() не возвращает значение в if
?
sizeof
не является функцией, это оператор. Скобки не являются частью имени оператора.size_t
, что приводит к "обычным арифметическим преобразованиям", в которых -1
преобразуется в unsigned, и в этом случае это очень большое число.В основном вы сравниваете 4 > 0xffffffffu
, или что-то близкое к этому, по крайней мере. Подробнее см. этот вопрос.
Неподписанное и подписанное целочисленное продвижение (точнее, "обычные арифметические преобразования" ). sizeof
дает значение типа size_t
, и по сравнению с беззнаковым значением (которое size_t
есть), -1 продвигается к этому типу и переполняется и становится огромным.
Незнакомое целочисленное переполнение имеет четко определенное поведение и должно приниматься как modulo 2 ^ width
, где width
- это количество бит в конкретном неподписанном целочисленном типе. Итак, если у вас есть 32-разрядная ширина size_t
и int
, например, ваше сравнение будет эквивалентно с
if (4 > 4294967295u)
что, очевидно, неверно.
sizeof(int)
и -1
.sizeof(int)
имеет тип size_t
, который гарантированно является целым числом без знака. На практике size_t
, скорее всего, будет как минимум равным unsigned int
для любой системы.-1
имеет тип int
, что эквивалентно signed int
.Это состояние (C11 6.3.1.8):
...
В противном случае, если тип операнда со знаком целочисленного типа может представляют все значения типа операнда без знака целочисленный тип, то операнд с целым числом без знака преобразуется к типу операнда со знаком целочисленного типа.
В противном случае оба операнды преобразуются в целочисленный тип без знака, соответствующий тип операнда со знаком целочисленного типа.
int
не может соответствовать всем значениям a size_t
.-1
преобразуется в целое число без знака. На практике size_t
скорее всего эквивалентен либо unsigned int, либо unsigned long. Что бы ни случилось, когда вы сохраняете -1 в такой переменной, это поведение, определяемое реализацией.0xFFFFFFFF
(количество FF зависит от размера int в данной системе).4 > 0xFFFFFFFF
оценивается как false.Sizeof - это оператор, который приводит к длинному int без знака. Следовательно, при сравнении unsigned long int с -1, который хранится как 0xffffffff
(размер int равен 4 байтам).
-1 по умолчанию является целым знаком. Но, в сравнении между подписанным int и unsigned int, компилятор идет с неявным typecasting подписанного int в unsigned int. Это приводит к тому, что unsigned -1 будет приблизительно равным 4.6giga-значению.
Следовательно, выход false
.
Просто проверьте это и убедитесь сами.
#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);
}