2

I found this code snipped in a bigger project and it really got me thinking.

float sift_handler(int rs2, int rs4, int rs5);
int result1;


float temp = sift_hander(rs2, rs4, rs5);
result1 = *(int*)&temp;

As I understand the address of the float temp is casted to an int pointer and then dereferenced. When I compile this code I get a warning

warning: dereferencing type-punned pointer will break strict-aliasing rules

What are the real benefits of this against result1 = temp? Also is it better to use round(), than just casting?

3 Answers3

2

What are the real benefits of this against result1 = temp?

They are completely different operations. result1 = temp converts value from float to integer. If temp is 1.0f, then result1 will be 1. If default rounding style (which is simply truncation) is not satisfactory, you can use round() before assignment to integer.

*(int*)&temp on the other hand reinterprets the bits of float variable and stores those bits to integer variable. 1.0f will likely result in some huge integer value. This is called type punning.

As compiler tells you, doing this derefrence with pointer of invalid type is strict aliasing violation. Correct way to do this type punning would be:

memcpy(&result, &temp, sizeof temp);
user694733
  • 15,208
  • 2
  • 42
  • 68
  • he wants to cast (get the integer part of it). memcpy will not help – 0___________ May 10 '19 at 09:52
  • @P__J__ It seems to me the question was only to clarify a confusion, rather than wanting to perform certain operation. – user694733 May 10 '19 at 10:00
  • This is the first time I hear of type punning. I taught it was just a funny way of casting. I would change this to `memcpy` than, for the violation not to be present anymore. – jacktorrancee May 10 '19 at 10:03
  • @Mladia If you have a lot of old code, you could disable strict aliasing with `-fno-strict-aliasing` (I assume you use gcc?). It should disable aliasing optimizations and make sure your current code doesn't break unexpectedly. – user694733 May 10 '19 at 10:31
2

It used to be an old trick to access the representation of a float. That means that it is not a cast and (if not caught by UB) will give a different result except for 0 in common implementation.

At least since C99 and C++11 (unsure for previous versions), doing that invokes Undefined Behaviour because it violates the strict aliasing rule. That rule was invented to help compiler in their optimization by stating that a variable could only be accessed through its own type or through a character type. That way when the compiler has stored a float in a register, it can assume that this float will not be changed by any integer change (very simplified explaination).

But as it used to be intensively used in older programs, most compilers (even recent ones) have an option to ignore the strict aliasing rule.

Here your compiler simply warns you that this code violates the strict aliasing rule and may cause UB on some implementations.

TL/DR: using a casted pointer to access a different type is an attempt to reinterprete the underlying representation and is UB on both C and C++. It is definitely not the same as a cast.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Useful information, thank you. Would one try to get rid of the warning somehow or just leave it like that? Is the `memcpy` a right way to do that (as stated in another answer)? I am reading about `memcpy` and type punning, but it is kind of hard to understand. – jacktorrancee May 10 '19 at 10:22
0

What are the real benefits of this against result1 = temp

It does something completely different and it does not cast the float to integer. So just do not use pointer punning at all, until you understand well the pointers, data types, its representation in the particular implementation etc etc

0___________
  • 60,014
  • 4
  • 34
  • 74