3 ポインタ配列

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

メモリ領域のイメージ

 ポインタ配列 *pstr[ ]の表記に関しては、次のことが成立します。  上記の例では、キーボードから入力した文字列をポインタ配列で表現しましたが、文字列が最初からわかっている場合は、次のようにしてポインタ配列を初期化することが可能です。
static char *week[] = {
  "Monday", "Tuesday", "Wednesday", "Thursday",
  "Friday", "Saturday", "Sunday"
};