ここでは、次のプログラムを例にとって、ポインタを要素として持つ配列を考えてみよう。int i; char *pstr[5]; /* 1. */ char str[100]; /* 2. */ for(i = 0; i < 5; i++){ scanf("%s", str); /* 3. */ pstr[i] = (char *)malloc(sizeof(char) * (strlen(str)+1)); /* 4. */ strcpy(pstr[i], str); /* 5. */ }このプログラムを実行し、文字列 "Monday"、"Tuesday"、"Wednesday"、 "Thursday"、"Friday"とキーボードから入力した場合のメモリ領域の状況を下図に示します。このようなデータ表現を使うと、可変長の文字列を効率よく扱えることがわかるでしょう。
- char *pstr[5]; の宣言は、pstrが5個の要素を持つ配列であり、 その各要素がchar型のデータを指し示すポインタであることを意味します。 これにより、pstr[0]自体はポインタ変数となりますので、 char型のデータを指すアドレスが格納されることになります。
- str[ ]は、キーボードから読み込んだ文字列を一時的に格納する配列です。
- scanf関数の%s指定子は、文字列の入力を指示しています。 そして、2番目の引数では、キーボードから入力された文字列を入れるべき文字 配列の先頭のアドレスを指定します。 ここでは、一時的に文字列を格納する配列 str[ ] の先頭アドレス str を指定 しています。
- strlen(str)関数は、指定した文字列(str)の文字長を計算して、 その値を返す関数であり、引数は調べたい文字列の先頭アドレスを指定します。 sizeof(char) * strlen(str) で、メモリ上で確保するメモリの大きさ(バイト数) を計算し、malloc関数で、その大きさのメモリ+1を確保し、確保したメモリの先頭 アドレスがpstr[i]に代入されます。
例えば、キーボードから"Hello"と入力したとしましょう。 そうすると、malloc関数では、char型のバイト数(1バイト)と文字の長さ5文字+1の 6文字の乗算を行い、合計6バイトのメモリ領域を確保することになります。- strcpy関数は、第1引数の指す文字列に、第2引数で指定した文字列をコピー します。両者とも文字列の先頭アドレスを指定します。 よって、ここでは、キーボードから入力された文字列strをメモリ確保で用意した pstr[i]で指される領域にコピーしたことになります。
ポインタ配列 *pstr[ ]の表記に関しては、次のことが成立します。上記の例では、キーボードから入力した文字列をポインタ配列で表現しましたが、文字列が最初からわかっている場合は、次のようにしてポインタ配列を初期化することが可能です。
- pstr[i]は、i番目に入力された文字列の先頭文字のアドレスを示します。
- *pstr[i]は、i番目に入力された文字列の先頭文字を示します。
- pstrは、ポインタ配列*pstr[ ]の先頭アドレスを示します。
- pstr[i]+2は、i番目に入力された文字列の先頭から3文字目が格納してある メモリのアドレスを示します。 同様に *(pstr[i]+2) は、3文字目の文字を示します。
static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };