所有 C 编译器在将浮点转换为整数时都会隐式删除小数吗?

问题描述 投票:0回答:2

我注意到在 GCC 和 Clang 下,当我将

float
值转换为
int
时,后端会执行一些操作将真正的浮点数据转换为整数 - 小数部分被忽略,而整数部分是被解释为
int
的部分。例如,表达式
( unsigned int ) 101.75f
的计算结果为
101

这很简洁,但我很好奇:这只是这些特定编译器内置的一些行为,还是实际上是 C 编程语言的必需功能?

如果是前一种情况,有什么方法可以禁用此功能吗?如果有一种超级简单的方法可以将

float
值天真地转换为
unsigned int
而不进行任何“实际”转换,我会很感兴趣。例如,我使用这个网页获得了
101.75f
的IEEE-754表示,即
01000010110010111000000000000000
。如果这 32 位天真地解释为
unsigned int
,我的原始表达式
( unsigned int ) 101.75f
将计算为
1120632832
而不是
101

c casting floating-point ieee-754
2个回答
0
投票

将浮点类型转换为整数类型会截断小数部分。这是由 C 标准第 6.3.1.4p1 节规定的:

当实浮点类型的有限值转换为整数时 除

_Bool
以外的类型,小数部分将被丢弃(即 值被截断为零)。如果积分部分的值 不能用整数类型表示,行为未定义。

这是因为显式转换(即强制转换)和隐式转换都会将表达式的 value 从一种类型转换为另一种类型。您似乎要问的是 float

representation
是否可以重新解释为
int

您可以使用

union
来执行这样的重新解释:

union {
    unsigned int i;
    float f;
} u;
u.f =  101.75f;
printf("%u\n", u.i);

-1
投票

这只是这些特定的编译器内置的一些行为,还是它实际上是 C 编程语言的必需功能?

这是C编程语言的一个特性。规范说:

当实浮点类型的有限值转换为

_Bool
以外的整数类型时, 小数部分被丢弃(即,该值被截断为零)。如果积分部分的值 不能用整数类型表示,行为未定义。

(C17 6.3.1.4/1;已添加强调)

您可以更普遍地将其理解为产生转换的类型转换,而不是对象表示的转换。

要将一个对象表示的字节复制到另一个对象中,请使用

memcpy()
或(在 C 中,但不是 C++)联合。

float my_float = 1.234567e+89;
uint32_t my_uint;

// with memcpy():
memcpy(&my_uint, &my_float, sizeof(my_uint));

// with a union:
union { float as_float; uint32_t as_int; } my_union = { .as_float = my_float };
uint32_t my_other_uint = my_union.as_int;
© www.soinside.com 2019 - 2024. All rights reserved.