C:铸造最小的32位整数(-2147483648)浮动给出正数(2147483648.0) [英] C: Casting minimum 32-bit integer (-2147483648) to float gives positive number (2147483648.0)

查看:314
本文介绍了C:铸造最小的32位整数(-2147483648)浮动给出正数(2147483648.0)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一个嵌入式项目时,我遇到了一些东西,我觉得很奇怪的行为。我设法重现它在codePAD(见下文)进行确认,但没有我的机器上的任何其他C编译器试试他们。

I was working on an embedded project when I ran into something which I thought was strange behaviour. I managed to reproduce it on codepad (see below) to confirm, but don't have any other C compilers on my machine to try it on them.

场景:我有一个的#define 为最负值的32位整数可以容纳,然后我尝试使用这个带有浮点值进行比较如下图所示:

Scenario: I have a #define for the most negative value a 32-bit integer can hold, and then I try to use this to compare with a floating point value as shown below:

#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链接: HTTP://$c$cpad.org/cBneMZL5

要我来说,它看起来好像这本code应该工作正常,但让我吃惊的它打印出宇宙坏了!

To me it looks as though this this code should work fine, but to my surprise it prints out The universe is broken!!.

这code隐式注塑 INT32_MIN 浮动,但事实证明,这导致 2147483648.0 的浮点值(正!),即使浮点类型是完全有能力再presenting的 -2147483648.0

This code implicitly casts the INT32_MIN to a float, but it turns out that this results in a floating point value of 2147483648.0 (positive!), even though the floating point type is perfectly capable of representing -2147483648.0.

没有人有任何见解的这种行为的原因是什么?

Does anyone have any insights into the cause of this behaviour?

code SOLUTION :由于史蒂夫·杰索普在他的答复中提到, limits.h中 stdint.h 包含正确的(工作) INT 范围定义一切已经,所以现在我使用这些不是我自己的的#define

CODE SOLUTION: As Steve Jessop mentioned in his answer, limits.h and stdint.h contain correct (working) int range defines already, so I'm now using these instead of my own #define

问题/解决方案说明摘要:提供的答案和讨论,我觉得这是发生了什么事情的一个很好的总结(注:也看答案/评论,因为它们提供了更详细的说明)

PROBLEM/SOLUTION EXPLANATION SUMMARY: Given the answers and discussions, I think this is a good summary of what's going on (note: still read the answers/comments because they provide a more detailed explanation):


  • 我使用的是C89编译器与32位 S,所以比 LONG_MAX 较大的值,并且小于或等于 ULONG_MAX 其次后缀的类型为无符号长

  • ( - 2147483648L)实际上是一个一元 - 上的无符号长(见previous点)值: - (2147483648L)。这种否定操作'包装'的值周围是 2147483648 的无符号长值(因为32位无符号长活动的 0 的范围 - 4294967295

  • 无符号长号的看起来的像预期的负 INT 价值时,它得到印刷作为一个 INT 或传递给函数,因为它是第一个得到强制转换为 INT ,它包裹了这一点-of范围 2147483648 各地 -2147483648 (因为32位 INT 活动的范围-2147483648到2147483647)

  • 演员到浮动,但是,使用实际无符号长 2147483648 转换,造成的浮点值 2147483648.0

  • I'm using a C89 compiler with 32-bit longs, so any values greater than LONG_MAX and less or equal to ULONG_MAX followed by the L postfix have a type of unsigned long
  • (-2147483648L) is actually a unary - on an unsigned long (see previous point) value: -(2147483648L). This negation operation 'wraps' the value around to be the unsigned long value of 2147483648 (because 32-bit unsigned longs have the range 0 - 4294967295).
  • This unsigned long number looks like the expected negative int value when it gets printed as an int or passed to a function because it is first getting cast to an int, which is wrapping this out-of-range 2147483648 around to -2147483648 (because 32-bit ints have the range -2147483648 to 2147483647)
  • The cast to float, however, is using the actual unsigned long value 2147483648 for conversion, resulting in the floating-point value of 2147483648.0.

推荐答案

在C89有32位 2147483648L 的类型 unsigned long int类型(见3.1.3.2整型常量)。所以一旦模运算已经应用到一元减运算, INT32_MIN 为正值2147483648类型无符号长

In C89 with a 32 bit long, 2147483648L has type unsigned long int (see 3.1.3.2 Integer constants). So once modulo arithmetic has been applied to the unary minus operation, INT32_MIN is the positive value 2147483648 with type unsigned long.

在C99, 2147483648L 已键入如果大于32位,或长长否则(见6.4.4.1整型常量)。因此,有没有问题, INT32_MIN 为负值-2147483648型长长

In C99, 2147483648L has type long if long is bigger than 32 bits, or long long otherwise (see 6.4.4.1 Integer constants). So there is no problem and INT32_MIN is the negative value -2147483648 with type long or long long.

与同样在C89 大于32位, 2147483648L 已键入 INT32_MIN 是负的。

Similarly in C89 with long larger than 32 bits, 2147483648L has type long and INT32_MIN is negative.

我猜您使用的是C89编译器具有32位

I guess you're using a C89 compiler with a 32 bit long.

看它的方法之一是,C99修复了C89一个错误。在C99十进制字面没有 U 后缀的总是的签署型,而C89则可能根据其价值进行带符号。

One way to look at it is that C99 fixes a "mistake" in C89. In C99 a decimal literal with no U suffix always has signed type, whereas in C89 it may be signed or unsigned depending on its value.

你应该做的,顺便说一句,是包括 limits.h中,并使用 INT_MIN 的最小值一个 INT LONG_MIN 为最低值。他们有正确的值的的所期望的类型( INT_MIN INT LONG_MIN )。如果你需要一个精确的32位类型,然后(假设你的实现是2的补码):

What you should probably do, btw, is include limits.h and use INT_MIN for the minimum value of an int, and LONG_MIN for the minimum value of a long. They have the correct value and the expected type (INT_MIN is an int, LONG_MIN is a long). If you need an exact 32 bit type then (assuming your implementation is 2's complement):


  • 为code不具有可移植,你可以使用任何类型的您preFER这是正确的尺寸,并声称它是在安全方面。

  • 为code具有可移植,搜索一个版本的C99头 stdint.h 上的C89编译器的工作原理,并使用 int32_t INT32_MIN

  • 如果一切都失败了,写 stdint.h 自己,并使用WiSaGaN的回答除权pression。它有键入 INT 如果 INT 至少为32位,否则

  • for code that doesn't have to be portable, you could use whichever type you prefer that's the correct size, and assert it to be on the safe side.
  • for code that has to be portable, search for a version of the C99 header stdint.h that works on your C89 compiler, and use int32_t and INT32_MIN from that.
  • if all else fails, write stdint.h yourself, and use the expression in WiSaGaN's answer. It has type int if int is at least 32 bits, otherwise long.

这篇关于C:铸造最小的32位整数(-2147483648)浮动给出正数(2147483648.0)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆