gcc4.7.3におけるvoid型の実装

void型について実験。gccのバージョンは、以下です。

gcc バージョン 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1) 

われわれはvoidを当たり前のように使っているけど、そもそもvoidとは何だろ?実装レベルで、どのようにコンパイラに解釈されているのか、また逆アセンブルしてみました。

「Cリファレンスマニュアル*1」によると、void型の使い方として、以下のケースが挙げられています。

・関数の返却値の型として、その関数は値を返さないことを表す.
・値を捨てることを明示したい場合にキャスト式の中で.
・「万能」データポインタvoid *型を作るために.
・関数が引数を持たないことを示すために、仮引数の並びの代わりに.

上記と矛盾するケース、つまり「void型の使用が許されないケース」において、実験的にvoid型を使用してみたところ、以下のコンパイルエラーが発生しました。メモとして記しておきます。

ケース ソースの例 使用した場合の物理的挙動
void型変数を宣言 void a; コンパイルエラー「‘n’ の記憶域サイズが不明です」
復帰値void型の関数の戻り値を呼出元で参照 (省略) コンパイルエラー「void の値が本来の意味通りに無視されませんでした」
復帰値void型の関数内でreturn 0 (省略) 同上

void型ポインタは何バイトで実装されているか

void型ポインタの領域を確保する際に、何バイト確保されるか?という実験。

  1 void func()
  2 {
  3     char a = 0x12;
  4     void *n = (void *)0x7F;
  5     char b = 0x34;
  6     int c = 0xFFFFFFFF;
  7 
  8     return;
  9 }

 

00000000 <func>:
   0:	55                   	push   ebp
   1:	89 e5                	mov    ebp,esp
   3:	83 ec 10             	sub    esp,0x10
   6:	c6 45 f6 12          	mov    BYTE PTR [ebp-0xa],0x12
   a:	c7 45 f8 7f 00 00 00 	mov    DWORD PTR [ebp-0x8],0x7f
  11:	c6 45 f7 34          	mov    BYTE PTR [ebp-0x9],0x34
  15:	c7 45 fc ff ff ff ff 	mov    DWORD PTR [ebp-0x4],0xffffffff
  1c:	90                   	nop
  1d:	c9                   	leave  
  1e:	c3                   	ret

局所変数に値を格納した後のスタックは、以下のようになっています。「7F」の格納先には、4バイト分の領域を確保しています。

ebp offset Stack esp
-0x10 (空き)
-0x0C __ __ 12 34
-0x08 ★7F __ __ __
-0x04 FF FF FF FF
0x00 Based EBP

まあ、参照先のデータ型によってポインタ型のサイズが異なる処理系はまれでしょうから、あまり意味の無い実験でした。

void型ポインタをポインタ演算

int型(を指す)ポインタ変数を+1すると、ポインタ値としては4加算されますが、ではvoid型ポインタ変数を+1すると、加算される値はいくつでしょうか。そこで、こんなコードを入れてみると…

printf("%p -> %p\n", n, n+1);
0x7f -> 0x80

結果は「+1される」でした。もちろん、処理系定義でしょうが。

復帰値がvoid型である関数における、eaxレジスタの扱い

leave/ret命令の前に、eaxレジスタに何かをセットするコードは存在しませんでした。つまり、呼出元で関数の復帰値を破棄する(void)のキャストはNOPであり、単に可読性のためでしょう。ちなみに、returnある/なしのコードをそれぞれコンパイルしたものを比較してみると、「return」ありのオブジェクトファイルにおいては、leave/retの直前にNOP命令が配置されていました。

今回の実験は、だから?って感じで、あまりパッとしなかったなあ。

*1:「Cリファレンスマニュアル 第5版」(S・P・ハービソン3世/G・L・スティール・ジュニア著 玉井浩訳(エスアイビー・アクセス))