我注意到在 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 标准第 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);
这只是这些特定的编译器内置的一些行为,还是它实际上是 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;