Я работал над встроенным проектом, когда я столкнулся с чем-то, что, по моему мнению, было странным поведением. Мне удалось воспроизвести его на кодовом коде (см. Ниже), чтобы подтвердить, но у меня нет других компиляторов 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!!");
}
}
Codepad link: http://codepad.org/cBneMZL5
Мне кажется, что этот код должен работать нормально, но, к моему удивлению, он выводит The universe is broken!!
.
Этот код неявно передает INT32_MIN
в float
, но оказывается, что это приводит к значению с плавающей запятой 2147483648.0
(положительный!), хотя тип с плавающей точкой отлично способен представлять -2147483648.0
.
Кто-нибудь может понять причину такого поведения?
РЕШЕНИЕ КОДОВ. Как сказал Стив Джессоп в своем ответе, limits.h
и stdint.h
уже содержат правильный (рабочий) int
диапазон define
, поэтому я теперь использую их моего собственного #define
ПРОБЛЕМА/РЕШЕНИЕ ОБЪЯСНЕНИЯ РЕЗЮМЕ: Учитывая ответы и дискуссии, я думаю, что это хорошее резюме того, что происходит (обратите внимание: все еще читайте ответы/комментарии, потому что они дают более подробное объяснение)
- Я использую компилятор C89 с 32-разрядным
long
s, поэтому любые значения, превышающиеLONG_MAX
и меньшие или равныеULONG_MAX
, за которыми следует постфиксL
, имеют типunsigned long
-
(-2147483648L)
на самом деле является унарным-
на значенииunsigned long
(см. предыдущую точку):-(2147483648L)
. Эта операция отрицания "обертывает" значение вокруг значенияunsigned long
2147483648
(поскольку 32-разрядныйunsigned long
имеет диапазон0
-4294967295
). - Этот номер
unsigned long
выглядит как ожидаемое отрицательное значениеint
, когда он печатается какint
или передается функции, потому что он сначала получает отличное отint
, которое обертывает это вне -range2147483648
вокруг-2147483648
(поскольку 32-разрядныйint
имеет диапазон от -2147483648 до 2147483647) - Приведение в
float
, однако, использует фактическое значениеunsigned long
2147483648
для преобразования, что приводит к значению с плавающей запятой2147483648.0
.