#include <stdio.h>
main()
{
if (sizeof(int) > -1)
printf("True");
else
printf("False");
}
Он печатает False
. Почему sizeof() не возвращает значение в if
?Оператор sizeof() в операторе if-statement
#include <stdio.h>
main()
{
if (sizeof(int) > -1)
printf("True");
else
printf("False");
}
Он печатает False
. Почему sizeof() не возвращает значение в if
?Оператор sizeof() в операторе if-statement
sizeof
не является функцией, это оператор. Скобки не являются частью имени оператора.size_t
, что приводит к «обычным арифметическим преобразованиям», в которых -1
преобразуется в unsigned, и в этом случае это очень большое число.В основном вы сравниваете 4 > 0xffffffffu
, или что-то близкое к этому как минимум. See this question для деталей.
Строго говоря, здесь нет целочисленного продвижения, а скорее _balancing_ (формально называемого «обычные арифметические преобразования»). – Lundin
преобразование '-1' в целое число без знака всегда дает максимальное значение, даже если представление не является дополнением двух. – Christoph
Благодаря @Lundin и Christoph, отредактирован. – unwind
Неподписанное и подписанное целочисленное продвижение (точнее, «обычные арифметические преобразования», если быть более точным). sizeof
дает значение типа size_t
, и по сравнению с неподписанным значением (которое size_t
есть), -1 продвигается к этому типу и переполняется и становится огромным.
Целое число без знака переполнения имеет вполне определенное поведение и должно быть принято, как по модулю, где 2^width
width
является число битов в конкретном типе целого числа без знака. Таким образом, если у вас есть 32-битная size_t
и int
, например, ваше сравнение будет эквивалентно
if (4 > 4294967295u)
, который, очевидно, неверно.
Отличный ответ, но не будет ли он переполнен, а не переполнен? – C0deH4cker
@ C0deH4cker Ну, все зависит от того, как вы его интерпретируете :) Я предпочитаю использовать «underflow» для чисел с плавающей запятой, когда число «x
А вот этот ответ (http://programmers.stackexchange.com/questions/32893/is-int-min-1-an-underflow-or-overflow) объясняет это, а также почему я был в замешательстве. – C0deH4cker
sizeof(int)
и -1
.sizeof(int)
имеет тип size_t
, который гарантированно является целым числом без знака. На практике, size_t
, скорее всего, будет, по крайней мере, размером с unsigned int
в любой системе.-1
имеет тип int
, что эквивалентно signed int
.Это состояние (C11 6.3.1.8):
...
В противном случае, если тип операнда с подписью целочисленного типа может представлять все значения типа операнда с непознанным целым типом , то операнд с целым целым числом без знака преобразуется в тип операнда со знаком целочисленного типа.
В противном случае оба операнда преобразуются в целочисленный тип без знака, соответствующий тип операнда со знаком целочисленного типа.
int
не может приспосабливать все значения в size_t
.-1
преобразуется в целое число без знака. На практике, size_t
, скорее всего, эквивалентен либо unsigned int, либо unsigned long. Что бы ни случилось, когда вы сохраняете -1 в такой переменной, это поведение, определяемое реализацией.0xFFFFFFFF
(количество FF зависит от размера int в данной системе).4 > 0xFFFFFFFF
оценивает значение false.«Что бы ни случилось, когда вы сохраняете -1 в такой переменной, это поведение, определяемое реализацией». Umm, единственная зависящая от реализации вещь - ширина 'size_t'. преобразование '-1' в неподписанный тип обязано приводить к максимальному значению этого типа по стандарту. –
@ DanielFischer Что я имел в виду, так это то, что способ распознавания целочисленного поведения является impl.defined. C позволяет дополнять друг друга, дополнять и т. Д. – Lundin
Где «и так далее» расширяется до «подписанного магната» или «знака и величины», в зависимости от того, какое имя вы предпочитаете. Таким образом, независимо от того, является ли преобразование просто усечением/переинтерпретацией/расширением знака или изменением битового шаблона по-другому, определяется реализацией, да. Но это не имеет значения, не так ли? Важным является результат. –
Просто проверить это и увидеть для себя
#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);
}
Sizeof является оператором, который приводит к беззнаковому долгому междунару. Следовательно, при сравнении unsigned long int с -1, который сохраняется как 0xffffffff
(размер int равен 4 байтам).
-1 по умолчанию обозначено целое число. Но, в сравнении между подписанным int и unsigned int, компилятор идет с неявным typecasting подписанного int в unsigned int. Это приводит к тому, что знак без знака -1 будет приблизительно равен значению 4.6giga.
Следовательно, выход false
.
Включите предупреждения компилятора. – Kos
'(sizeof (int)> -1)' = '(4u> -1)' = '(4u> -1u)' = '(4u> -1u)' или '(4u> 4294967295uu)' потому что '- 1u == 4294967295u' = 'False' =' 0' –