Я работал над встроенным проектом, когда столкнулся с чем-то, что показалось мне странным. Мне удалось воспроизвести это на кодовой панели (, см. ниже ), чтобы подтвердить, но у меня нет других компиляторов C на моей машине, чтобы попробовать это на них.
Сценарий :У меня есть #define
для самого отрицательного значения, которое может содержать 32 -битное целое число, а затем я пытаюсь использовать его для сравнения со значением с плавающей запятой, как показано ниже:
#define INT32_MIN (-2147483648L)
void main()
{
float myNumber = 0.0f;
if(myNumber > INT32_MIN)
{
printf("Everything is OK");
}
else
{
printf("The universe is broken!!");
}
}
Ссылка на кодовую панель:http://codepad.org/cBneMZL5
Мне кажется, что этот код должен работать нормально, но, к моему удивлению, он выводит The universe is broken!!
.
Этот код неявно приводит INT32_MIN
к float
, но оказывается, что это приводит к значению с плавающей запятой2147483648.0
(позитив! ), даже несмотря на то, что тип с плавающей запятой вполне способен представлять -2147483648.0
.
Кто-нибудь знает причину такого поведения?
КОД РЕШЕНИЕ:Как упомянул Стив Джессоп в своем ответе, limits.h
и stdint.h
содержат правильную (работу)int
range define
уже есть, так что теперь я использую их вместо своих собственных#define
ПРОБЛЕМА/РЕШЕНИЕ ОБЪЯСНЕНИЕ ОБЗОР:Учитывая ответы и обсуждения, я думаю, что это хорошее резюме того, что происходит (примечание :по-прежнему читайте ответы/комментарии, потому что они содержат более подробное объяснение):
long
, поэтому любые значения больше LONG_MAX
и меньше или равны ULONG_MAX
, за которыми следует постфикс L
, имеют типunsigned long
(-2147483648L)
на самом деле является унарным -
наunsigned long
(см. предыдущий пункт )значение:-(2147483648L)
.Эта операция отрицания «обертывает» значение вокруг значения unsigned long
значения 2147483648
(. потому что 32 -бит unsigned long
имеют диапазон0
-4294967295
).unsigned long
число выглядит как ожидаемое отрицательное int
значение, когда оно печатается как int
или передается в функцию, потому что оно сначала приводится к int
, которое обертывает это из -из -диапазона 2147483648
примерно до-2147483648
(потому что 32 -бит int
имеют диапазон -от 2147483648 до 2147483647)float
использует фактическое unsigned long
значение 2147483648
для преобразования, что приводит к плавающему значению -точки 2147483648.0
.