Does this pointer casting break strict aliasing rule?

放肆的年华 提交于 2019-12-04 02:52:54

Yes, this code is badly broken and invokes undefined behavior. In particular, notice these two lines:

    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking

Since the object *(long *)&y has type long, the compiler is free to assume it cannot alias an object of type float; thus, the compiler could reorder these two operations with respect to one another.

To fix it, a union should be used.

Yes, it breaks aliasing rules.

In modern C, you can change i = * (long *) &y; to:

i = (union { float f; long l; }) {y} .l;

and y = * (float *) &i; to:

y = (union { long l; float f; }) {i} .f;

Provided you have guarantees that, in the C implementation being used, long and float have suitable sizes and representations, then the behavior is defined by the C standard: The bytes of the object of one type will be reinterpreted as the other type.

Yes, it breaks aliasing rules.

The cleanest fix for things like i = * ( long * ) &y; would be this:

  memcpy(&i, &y, sizeof(i)); // assuming sizeof(i) == sizeof(y)

It avoids issues with alignment and aliasing. And with optimization enabled, the call to memcpy() should normally be replaced with just a few instructions.

Just as any other method suggested, this approach does not fix any problems related to trap representations. On most platforms, however, there are no trap representations in integers and if you know your floating point format you can avoid floating point format trap representations, if there are any.

i = * ( long * ) &y;

This breaks aliasing rules and therefore invokes undefined behavior.

You are accessing object y with a type different than float, or a signed / unsigned variant of char.

y = * ( float * ) &i;

This statement above also breaks aliasing rules.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!