【深堀 C++】static_castの仕組みを探る

イントロダクション

C++において、型変換(以降:キャスト)は頻繁に使用される操作の一つです。

しかし、キャストがコンパイラ、または実行時にどのように動作しているのか、知らなくても何とかなることが多いですが、キャストの内部処理に興味を惹かれたのでこの記事を作成しました。

この記事では特に、static_castについてどのようなどうなになっているのかを、実行時のレジスタ上のデータ変換を中心に解説し、さらにアセンブリコードも交えて詳しく説明していきます。

static_castの疑問

ここでは、なぜstatic_castのことを調べようと思ったのかについての話なので、興味がない方は読み飛ばしてください

  • 疑問1: static_castはよく使うが、どこでどのようにデータを変換しているのか気になる
  • 疑問2: キャストによってデータが失われる(切り落とされる)可能性がある場合、そのキャストはどのように扱われるのか?

これらの疑問点が解決できることを目標に今回の記事を作成しました。

メモリとレジスタを使いキャストする

まず、キャストがどのように動作するかを理解するためには、メモリレジスタの関係を知る必要があります。

例: intからcharへのキャスト

C++
int i = 300;
char c = static_cast<char>(i);

この例では、int型の300をchar型にキャストしています。

int型は通常4バイト(32ビット)、char型は1バイト(8ビット)です。

このような場合、char型の範囲(通常は-128から127)に収まらない値をキャストすると、データの上位ビットが切り落とされ、このキャストの実行結果は、44になります。

上位ビットが切り落とされるというのは、以下のようなイメージです。

300(10進) = 1 0010 1100(2進)

int型は32ビットなので、それを8ビットにするために下位ビットから8ビットまでで切り離します

char c = 0010 1100(2進)
char c = 32 + 8 + 4 = 44(10進)

なぜレジスタにロードするのか

実行時のレジスタでの処理

キャストが実行されるとき、データはまずメモリからレジスタにロードされ、そこで必要な型変換が行われます。

これをアセンブリコードで詳しく見てみましょう。

アセンブリコードで見る型変換の実際

以下のコードをコンパイルし、生成されたアセンブリコードを確認します。

C++
int main() {
    int i = 300;
    char c = static_cast<char>(i);
    return 0;
}

コンパイルされたアセンブリコードの一部は次のようになります。

ASM
mov         dword ptr [i], 12Ch   ; i に 300 (12Ch) を格納
mov         eax, dword ptr [i]    ; i の値を eax レジスタにロード
mov         byte ptr [c], al      ; eax の下位8ビットを c に格納

アセンブリコードの解説

  1. メモリにiの値(300、16進数で12C)を格納しています。
    mov dword ptr [i], 12Ch
  2. メモリ上のiの値をeaxレジスタにロードします。この時点で、eaxには300が格納されます。
    mov eax, dword ptr [i]
  3. eaxレジスタの下位8ビットをcに格納します。aleaxの下位8ビットを指します。ここでは、300の下位8ビット(16進数で44、10進数で68、ASCIIコードでD)がcに格納されます。
    mov byte ptr [c], al

なぜレジスタで型変換をするのか

キャストは基本的にメモリから計算対象のデータをレジスタに読み込むときに変換します。

なので厳密にはデータのやり取りの時に型変換を行っていることになります。

プログラムの原則として、元のデータ(メモリ上のデータ)を変更するのはあまりいい方法ではないとされています。

なので、メモリからデータを読み込む際に型変換を行い、レジスタ内では指定した型としてデータを扱うことで計算結果を型変換後の型で計算したものとして扱うことができるということでした。

まとめ

今回は、書籍にはあまり乗っていないようなニッチな部分を調べてみました。

static_cast以外に、dynamic_castなどほかにもキャストの種類がありますが、これらはもう少し知識がついてきたらまた調べてみようと思っています。

個人的にはこのような根本的な考え方を学ぶのが好きなので、また気になったことが出てきたら調べてまとめてみようと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA