dereferencing type-punned pointer will break strict-aliasing の警告を回避する方法.
C/C++では,以下のようなType-punned pointerを使うコードは,厳密には動作が保証できない.
float f = 123; uint32_t u = *(uint32_t*)&f;
このようなコードは,例えば GCCで "-O3 -Wall"のようなオプションを付けてコンパイルすると
dereferencing type-punned pointer will break strict-aliasing
という警告が出る.理由は,以下のURLあたりが詳しい.
で,肝心の解決方法は, union を使って以下のように書きなおすのが良いらしい.
typedef union { float f; uint32_t u; } union32_t; #define POINTER_TO_UINT32(p) (((union32_t*)(p))->u) #define POINTER_TO_FLOAT32(p) (((union32_t*)(p))->f) float f=123; uint32_t u = POINTER_TO_UINT32(&f);
このunionを使う方法は移植性が高いらしく, ffmpeg ライブラリの実装等で時々目にする.
なお別解としては,char*に一度キャストする方法
float f=123; char *tmp = &f; uint32_t u = *(uint32_t*)tmp;
memcpyしちゃう方法
float f=123; uint32_t u; memcpy(&u, &f, sizeof(u));
がある.
さらにGCC限定であれば,
- 変数の属性に __attribute__( (may_alias ) ) を付ける方法
- GCCのオプションに-fno-strict-aliasing を付ける方法
もある.