我发现这段代码被截断在一个更大的项目中,这确实让我思考。
float sift_handler(int rs2, int rs4, int rs5);
int result1;
float temp = sift_hander(rs2, rs4, rs5);
result1 = *(int*)&temp;
据我了解,浮点数temp
的地址被强制转换为int指针,然后被取消引用。编译此代码时,我会得到警告
warning: dereferencing type-punned pointer will break strict-aliasing rules
这样做的真正好处是什么
result1 = temp
?使用round()
比仅投射更好吗?
答案 0 :(得分:2)
针对result1 = temp的实际好处是什么?
它们是完全不同的操作。 result1 = temp
将值从float转换为整数。如果temp
为1.0f
,则result1
将为1
。如果默认的舍入样式(只是截断)不令人满意,则可以在分配给整数之前使用round()
。
*(int*)&temp
重新解释变量float
的位并将这些位存储到整数变量中。 1.0f
可能会导致一些巨大的整数值。这称为 type punning 。
正如编译器告诉您的那样,使用无效类型的指针进行这种取消引用是严格混叠违反。进行这种类型的校正的正确方法是:
memcpy(&result, &temp, sizeof temp);
答案 1 :(得分:2)
访问浮点数的表示曾经是一个古老的技巧。这意味着它不是强制转换,并且(如果未被UB捕获)将给出不同的结果,但在常见实现中为0。
至少从C99和C ++ 11起(不确定以前的版本),这样做会调用未定义行为,因为它违反了严格的别名规则。发明该规则是为了帮助编译器优化,方法是声明只能通过自己的类型或字符类型来访问变量。这样,当编译器将浮点数存储在寄存器中时,可以假定该浮点数不会因任何整数更改而被更改(非常简单的解释)。
但是,由于以前在较旧的程序中大量使用它,因此大多数编译器(甚至是最近的编译器)都可以选择忽略严格的别名规则。
在这里,您的编译器只是警告您此代码违反了严格的别名规则,在某些实现上可能会导致UB。
TL / DR:使用强制类型转换的指针访问其他类型是尝试重新解释基础表示,并且在C和C ++上都是UB。绝对和演员不同。
答案 2 :(得分:0)
针对result1 = temp的实际好处是什么
它所做的事情完全不同,并且没有将浮点数强制转换为整数。因此,完全不要使用指针修剪,直到您充分了解指针,数据类型,其在特定实现中的表示方式等