使用gcc将float转换为C中的unsigned int [英] cast float to unsigned int in C with gcc

查看:356
本文介绍了使用gcc将float转换为C中的unsigned int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用gcc测试从float到unsigned int之间的一些简单转换.

I am using gcc to test some simple casts between float to unsigned int.

下面的代码给出的结果为0.

The following piece of code gives the result 0.

const float maxFloat = 4294967295.0;
unsigned int a = (unsigned int) maxFloat;
printf("%u\n", a);

0被打印(我相信这很奇怪).

0 is printed (which I belive is very strange).

另一方面,以下代码:

const float maxFloat = 4294967295.0;
unsigned int a = (unsigned int) (signed int) maxFloat;
printf("%u\n", a);

打印出我相信的2147483648是正确的结果.

prints 2147483648 which I belive is the correct results.

我得到2个不同的结果怎么办?

What happens that I get 2 different results?

推荐答案

如果您首先这样做:

printf("%f\n", maxFloat);

您将获得的输出是这样:

The output you'll get is this:

4294967296.000000

假设float被实现为IEEE754单精度浮点类型,则由于没有足够的精度位,因此无法精确地用此类型表示值4294967295.0.它可以存储的最接近值是4294967296.0.

Assuming a float is implemented as an IEEE754 single precision floating point type, the value 4294967295.0 cannot be represented exactly by this type because there's aren't enough bits of precision. The closest value it can store is 4294967296.0.

假设int(同样是unsigned int)为32位,则值4294967296.0不在这两种类型的范围内.当值不能以给定的整数类型表示时,将浮点类型转换为整数类型会调用未定义的行为.

Assuming an int (and likewise unsigned int) is 32 bits, the value 4294967296.0 is outside the range of both of these types. Converting a floating point type to an integer type when the value cannot be represented in the given integer type invokes undefined behavior.

这在 C标准规定了从浮点类型到整数类型的转换:

This is detailed in section 6.3.1.4 of the C standard which dictates conversion from floating point types to integer types:

1 将实数浮点型的有限值转换为_Bool以外的整数类型时,小数部分将被丢弃(即, 该值将被截断为零).如果积分部分的值 61)

1 When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.61)

...

61)整数类型的值时执行的余数运算 的值转换为无符号类型时,无需执行 实数浮点型将转换为无符号型.因此,范围 可移植的实际浮点值为(−1,Utype_MAX + 1).

61) The remaindering operation performed when a value of integer type is converted to unsigned type need not be performed when a value of real floating type is converted to unsigned type. Thus, the range of portable real floating values is (−1, Utype_MAX+1).

以上段落中的脚注是第6.3.1.3节,其中详细介绍了整数到整数的转换:

The footnote in the above passage is referencing section 6.3.1.3, which details integer to integer conversions:

1 将整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新的表示 类型,它保持不变.

1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

2 否则,如果新类型是无符号的,则通过反复将最大值减去以下值再加上或减去一个值来转换该值 可以用新类型表示,直到该值在 新类型.

2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

3 否则,将对新类型进行签名并且无法在其中表示值;结果要么是实现定义的,要么是 实施定义的信号被引发.

3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

您在第一个代码段中看到的行为与所讨论的值是整数时超出范围转换为无符号类型一致,但是,因为要转换的值具有浮点类型,这是未定义的行为.

The behavior you see in the first code snippet is consistent with an out-of-range conversion to an unsigned type when the value in question is an integer, however because the value being converted has a floating point type it is undefined behavior.

仅因为一个实现可以做到这一点并不意味着万事大吉.实际上,如果您更改优化设置,gcc会得出不同的结果.

Just because one implementation does this doesn't mean that all will. In fact, gcc gives a different result if you change the optimization settings.

例如,在我的使用gcc 5.4.0的计算机上,给出以下代码:

For example, on my machine using gcc 5.4.0, given this code:

float n = 4294967296;
printf("n=%f\n", n);
unsigned int a = (unsigned int) n;
int b = (signed int) n;
unsigned int c = (unsigned int) (signed int) n;
printf("a=%u\n", a);
printf("b=%d\n", b);
printf("c=%u\n", c);

我用-O0得到以下结果:

I get the following results with -O0:

n=4294967296.000000
a=0
b=-2147483648
c=2147483648

还有-O1:

n=4294967296.000000
a=4294967295
b=2147483647
c=2147483647

另一方面,如果将n定义为longlong long,则始终会得到以下输出:

If on the other hand n is defined as long or long long, you would always get this output:

n=4294967296
a=0
b=0
c=0

如上所示,由C标准很好地定义了向无符号的转换,并且由实现定义了对符号的转换,该实现

The conversion to unsigned is well defined by the C standard as sited above, and the conversion to signed is implementation defined, which gcc defines as follows:

当值不能在对象中表示时,将整数转换为有符号整数类型的结果或发出的信号 该类型(C90 6.2.1.2,C99和C11 6.3.1.3).

The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 and C11 6.3.1.3).

要转换为宽度为N的类型,该值将以2 ^ N为模减少 在类型范围内;没有信号.

For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised.

这篇关于使用gcc将float转换为C中的unsigned int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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