ぼんさい塾

ぼんさいノートと補遺に関する素材や注釈です.ミスが多いので初稿から1週間を経た重要な修正のみ最終更新日を残しています.

Cの文法 (9)

2010-08-28 22:40:46 | 暮らし
「まず覚える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のポインタ