「まず覚えるCの文法」
(校正中)
P35: ポインタの配列
//-------------------------------------
#include <stdio.h>
char s[]="Hello.";
int main(void){
char *p[2];
p[0]=s; p[1]="How are you?";
printf("%s %s\n", p[0], p[1]);
printf("p[0]==%d, p[1]==%d\n",
p[0], p[1]);
printf("p[1][4]==%c\n", p[1][4]);
return 0;
}
//-------------------------------------
P36: ポインタへのポインタ
//-------------------------------------
#include <stdio.h>
char s[]="Hello.";
int main(void){
char *p[2], **q;
p[0]=s; p[1]="How are you?";
q=p; printf("q[1][4]==%c\n", q[1][4]);
return 0;
}
//-------------------------------------
P37: 紛らわしい例
//-------------------------------------
#include <stdio.h>
int m[2][3]={{5},{6,7}};
int main(void){
int *p[2]={m[1], m[0]}, (*q)[3]=m[1];
printf("p[0][1]==%d\n", p[0][1]);
printf("q[0][1]==%d\n", q[0][1]);
printf("m[1]==%d\n", m[1]);
printf("m+1==%d\n", m+1);
printf("&m[1]==%d\n", &m[1]);
printf("m==%d\n", m);
return 0;
}
//-------------------------------------
|
P35 のプログラムの「char *p[2];」はポインタの配列の
宣言で,p[0], p[1]を独立に文字列へのポインタとして
使うことができます.
・「[]」の方が「*」よりも「p」との演算の優先度が高い
ので「char *p[2];」は「char *(p[2]);」を意味します
[#37].Cの表現ではありませんが,便宜的に
char *(p[2]);
(char*) p[2]; p[2] の配列要素は(char*)
(char*)[2] p; p は(char*)の配列
と解釈することができます.
・「p[1]="How are you?";」を実行すると,メモリ内に
適当な領域を確保して文字列 "How are you?" を格納し
その先頭アドレスを p[1] に設定します.
・p[1][4] は アドレス p[1]+4 のデータ *(p[1]+4) を
表わしています.
P36 のプログラムの「char **q;」はポインタへのポインタ
の宣言です.「q=p;」の実行により p の代わりに q を使
うことができます.
・このプログラムでは q の有効性を見出せませんが,関数
の引数ではポインタへのポインタが必要になります.上記
の「 p の代わりに q を使える」というのがポイントです.
Cには多数の演算子が定義されてどの教科書・参考書にも
演算子の優先度と結合規則の表が示されています(@37).
「x < (y & 7)」の括弧は除去できない等,間違いやすい
関係もあるので,慣れるまでは栞を挟んで適宜参照できる
ようにしましょう.
「char *p[2];」の意味は P35 で述べましたが,P37 のプロ
グラムで「char (*p)[2];」との違いを見てください.
・p は整数へのポインタの配列,q は整数の配列へのポイン
タです.
・m+1==&m[1] ですが, &m[1]==m[1] として扱われます.
・つねに p[i][k]==(p[i])[k], p[0][k]==(*p)[k].
・q[1] は存在しないので「q[1]=m;」はエラーになりますが
「q[i][k]=0;」は i!=0 でもエラーにならず,例えば
printf("q[-1][0]==%d\n", q[-1][0]);
を実行すると m[0][0] の値が出力されます.p も同様です.
参考資料:自分で調べるCのポインタ
|