C :Приведение минимального 32-битного -целого числа (-2147483648 )к веществу с плавающей запятой дает положительное число (2147483648.0)

Я работал над встроенным проектом, когда столкнулся с чем-то, что показалось мне странным. Мне удалось воспроизвести это на кодовой панели (, см. ниже ), чтобы подтвердить, но у меня нет других компиляторов 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содержат правильную (работу)intrange defineуже есть, так что теперь я использую их вместо своих собственных#define

ПРОБЛЕМА/РЕШЕНИЕ ОБЪЯСНЕНИЕ ОБЗОР:Учитывая ответы и обсуждения, я думаю, что это хорошее резюме того, что происходит (примечание :по-прежнему читайте ответы/комментарии, потому что они содержат более подробное объяснение):

  • Я использую компилятор C89 с 32 -битами 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.

14
задан avanzal 31 July 2012 в 13:23
поделиться