当我遇到一些我认为奇怪的行为时,我正在做一个嵌入式项目。我设法在键盘上重现它(见下文)以确认,但我的机器上没有任何其他 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
为 a float
,但事实证明这会导致浮点值2147483648.0
(正!),即使浮点类型完全能够表示-2147483648.0
。
有没有人对这种行为的原因有任何见解?
代码解决方案:正如史蒂夫杰索普在他的回答中提到的,limits.h
并且已经stdint.h
包含正确的(工作)int
范围define
,所以我现在使用这些而不是我自己的#define
问题/解决方案解释摘要:鉴于答案和讨论,我认为这是对正在发生的事情的一个很好的总结(注意:仍然阅读答案/评论,因为它们提供了更详细的解释):
- 我正在使用具有 32 位
long
s 的 C89 编译器,因此任何大于LONG_MAX
和小于或等于后缀的值都有一种ULONG_MAX
类型L
unsigned long
(-2147483648L)
实际上是-
(见前unsigned long
一点)值的一元:-(2147483648L)
. 此否定操作将值“包装”为的unsigned long
值2147483648
(因为 32 位unsigned long
s 具有范围0
-4294967295
)。- 这个
unsigned long
数字在打印为 an或传递给函数时看起来像预期的负值,因为它首先被强制转换为 an ,它将这个超出范围的范围包装为(因为 32 位s 的范围为 -2147483648至 2147483647)int
int
int
2147483648
-2147483648
int
- 但是,强制转换
float
为使用实际unsigned long
值2147483648
进行转换,从而产生 的浮点值2147483648.0
。