【配列とポインタ】第5回 char **argvを実装してみる(1)
main()の引数である、「char **argv」の擬似変数「char **argv2」を実装してみます。
- 引数文字列の実体をスタックの連続領域に作成し、
- 各文字列の位置情報を管理するポインタ配列を作成し、
- ポインタ配列の位置情報をargv2に格納する
という流れでやっていきます。
まず、引数文字列の実体の作成から。
char string_0[] = "aaa"; char string_1[] = "bbb"; char string_2[] = "ccc";
これで、引数文字列の実体が、メモリ上に作成できました。
location | data | type |
---|---|---|
00000000 | "aaa\0" | char[] |
00000004 | "bbb\0" | char[] |
00000008 | "ccc\0" | char[] |
ちなみに、これらの文字列の実体が、アドレスの昇順にかつ宣言順にスタックの連続領域に格納されることが保証されていれば、例えば「*(&arr_0+1)」のような式で、隣の"bbb"を参照できます(移植性が低下するのでやるべきではありませんが)。
つぎに、これら文字列のアドレスを管理する、ポインタ配列を作成します。
char *arr_list[4]; arg_list[0] = string_0; arg_list[1] = string_1; arg_list[2] = string_2; arg_list[3] = NULL;
location | data | type |
---|---|---|
AAAAAAA0 | 00000000 | char * |
AAAAAAA4 | 00000004 | char * |
AAAAAAA8 | 00000008 | char * |
注意したいのは、ポインタ配列の各要素が格納しているのは、配列へのポインタではなく「配列の先頭要素へのポインタ」ということです。でないと、char **argvに代入することができません。
以下に、参照関係を示します。
location | data | type | location | data | type | |
---|---|---|---|---|---|---|
AAAAAAA0 | 00000000 | char * | ===> | 00000000 | "aaa\0" | char [] |
AAAAAAA4 | 00000004 | char * | ===> | 00000004 | "bbb\0" | char [] |
AAAAAAA8 | 00000008 | char * | ===> | 00000008 | "ccc\0" | char [] |
ここまでで、ポインタ配列arg_listをメモリ上に格納したわけですが、本物のargvと同じように、arg_listの先頭要素へのポインタ(&arg_list[0])がメモリ上に格納されるのも再現します。
char **argv2;
argv2 = arg_list;
location | data | type |
---|---|---|
FFFFFFF0 | AAAAAAA0 | char ** |
以下に、全体の参照関係を示します。
addr | data | type | location | data | type | location | data | type | ||
---|---|---|---|---|---|---|---|---|---|---|
FFFFFFF0 | AAAAAAA0 | char ** | ===> | AAAAAAA0 | 00000000 | char * | ===> | 00000000 | "aaa\0" | char [] |
AAAAAAA4 | 00000004 | char * | ===> | 00000004 | "bbb\0" | char [] | ||||
AAAAAAA8 | 00000008 | char * | ===> | 00000008 | "ccc\0" | char [] |
ちなみに、以下のように一発で書くこともできますが、ただ、これだと文字列の実体がスタックに積まれずに.rodataに作成されるので、本物とはちょっと違うものになってしまいます。
1 char *arg_list[4] = {"aaa","bbb","ccc",NULL}; 2 char **argv2 = arg_list;
今回は、説明のために二次元配列を使わずにベタなコーディングをしていますが、次回は二次元配列とループを使った冗長性のない書き方をしてみたいと思います。