取消引用指针广播变量的地址

时间:2019-05-10 09:43:34

标签: c pointers

我发现这段代码被截断在一个更大的项目中,这确实让我思考。

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()比仅投射更好吗?

3 个答案:

答案 0 :(得分:2)

  

针对result1 = temp的实际好处是什么?

它们是完全不同的操作。 result1 = temp将值从float转换为整数。如果temp1.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的实际好处是什么

它所做的事情完全不同,并且没有将浮点数强制转换为整数。因此,完全不要使用指针修剪,直到您充分了解指针,数据类型,其在特定实现中的表示方式等