float <-> intなどのreinterpret_cast

float型の変数に対してビット演算等を行いたい場合,一度ビット演算の定義されているint等にキャストしてから演算を行い,再びfloatに戻すということが必要になる.

int i = reinterpret_cast<int>(f);
では
エラー: invalid cast from type ‘float’ to type ‘int’
のようにエラーが出る.

どう書くか

ポインタを介して書くことで期待するコードを書くことができる.

int i = *reinterpret_cast<int*>(&f);

x86_64ではどうなるか

ただキャストするだけのC++コード
gcc main.cpp -S
する. スタックフレーム周りと返り値処理の間の部分がキャスト部分なので
	movss	.LC0(%rip), %xmm0
	movss	%xmm0, -8(%rbp)
	leaq	-8(%rbp), %rax
	movl	(%rax), %eax
	movl	%eax, -4(%rbp)
が該当箇所である.順に見てみると
  1. xmm0レジスタに1065353216を格納

    1065353216は0b111111100000000000000000000000であり,1.0fの中身を10進数表記したもの. 今回はキャスト対象がコンパイル時に判明している.

  2. -8(%rbp)にmove
  3. -8(%rbp)の実効アドレス計算
  4. 実効アドレス先読み込み
といった形となっている.
特にC++コードの意味が変更されることなくアセンブリに落とされている.

ポインタ→unsigned long

64bitとなったためにベースポインタからの位置が-8から-12となっている以外そこまで変わらないですね.
カテゴリー:C++
記事作成日:2018-12-03