「まず覚えるCの文法」
(校正中)
P32: ポインタ
//-------------------------------------
#include <stdio.h>
char s[]="Hello.";
int main(void){
char *p; int k=0, *q=&k;
for(p=s; *p!='\0'; p++){
printf("%c", *p); k++;
}
printf(" k==%d, *q==%d\n", k, *q);
return 0;
}
//-------------------------------------
P32A: 配列もどきの表現
//-------------------------------------
#include <stdio.h>
char s[]="abcdefgh";
int main(void){
char *p=s+2; int i, *q=s;
for(i=-1; i<3; i++){
printf("i=%2d, p[i]==%c,==%x, "
"*(p+i)==%x\n",
i, p[i], p[i], *(p+i));
}
printf("q[0]==%x\n", q[0]);
printf("q[1]==%x\n", q[1]);
return 0;
}
//-------------------------------------
P34: 2次元の配列
//-------------------------------------
#include <stdio.h>
int m[2][3]={{5},{6,7}};
char s[2][8]={"abcde", "xyz"};
int main(void){
int i,k;
for(i=0; i<2; i++){
for(k=0; k<3; k++){
printf("m[%d][%d]==%d, ",
i, k, m[i][k]);
}
printf("s[%d]==%s\n", i, s[i]);
}
return 0;
}
//-------------------------------------
P34A: アドレス
//-------------------------------------
#include <stdio.h>
int m[2][3]={{5},{6,7}};
int main(void){
int i, k, *p=&m[0][2];
for(i=0; i<2; i++){
for(k=0; k<3; k++){
printf("&m[%d][%d]==%d, ",
i, k, &m[i][k]);
}
printf("\nm[i]==%d\n", m[i]);
}
printf("m==%d\n", m);
printf("p[1]==%d, p+1==%d\n",
p[1], p+1);
return 0;
}
//-------------------------------------
|
変数の先頭アドレスを記憶する変数をポインタといいます
(#32).P32 のプログラムの「char *p;」はポインタ p の
値を先頭アドレスとする 1 バイト(sizeof(char)==1)の
領域を char 型の変数として使うことを宣言します.
Cではこの領域が char 型の変数用に確保されているか
否かはチェックしません.p の値がおかしいと *p にデー
タを書き込むことにより,機械語命令を破壊する可能性が
あります.
・Cのプログラムは関数の集まりですが,引数はすべて値
呼びのため,ポインタが多用されます.
・ポインタは先頭アドレスのみを記憶し,データの型は
コンパイルラが所定の場所に記憶します.
・「*p」の「*」を間接演算子,「&k」の「&」をアドレス
演算子といいます.*(&k)==k; q==&(*q) です.
・配列要素 m[i] も *(m+i) と表現できます.
ポインタが指すデータの構造はポインタの宣言のみで決まり
ます.このことを P32A のプログラムで確認してください.
p[i] は常に(i<0 でも)*(p+i) と等価
ですが,p[i] を配列要素とする配列は存在しません(#31&).
・printf() の書式「%x」は16進表示の指定です.
・宣言「int i, *q=s;」によって(*q ではなく)q が s に
初期化され
q[0]==64636261
q[1]==68676665
と表示されます.これは
q[0]=(((s[3]*16)+s[2])*16+s[1])*16+s[0]
q[1]=(((s[7]*16)+s[6])*16+s[5])*16+s[4]
を意味します.
・「int *q;」を「int* q;」と同じですが,「int* p, q;」は
「int *p, *q;」とは異なります(#32&).
Cでは2行3列の int 型変数の配列を「int m[2][3];」の
ように宣言します.文字列の配列は char 型の2次元配列と
して宣言します.P34 のプログラムをコピー,実行して配列
要素がどのように初期化されるか調べてください.
・m,s は外部変数なので初期値を指定していない要素は 0
に初期化されます(#30).
・m[i][k],s[i][k] の先頭アドレスは &m[i][k],&s[i][k]
です.また,m[i],s[i],m,s はアドレスで
m[i]==&m[i][0], s[i]==&s[i][0], m==m[0], s==s[0]
・int m[][3]={{5},{6,7}}; char s[][8]={"abcde", "xyz"};
は
int m[][2]={{5},{6,7}};
char s[][8]={"abcde", "xyz"};
と等価です.
配列要素の先頭アドレスを P34A のプログラムで調べること
ができます.実行例は
&m[0][0]==4235560, &m[0][1]==4235564, &m[0][2]==4235568,
m[i]==4235560
&m[1][0]==4235572, &m[1][1]==4235576, &m[1][2]==4235580,
m[i]==4235572
m==4235560
p[1]==6, p+1==4235572
・プログラムを変更することにより
&m[0][2]==m[0]+2
&m[0][5]==m[0]+5, m[0]+5==&m[1][2]
等も確認できます.
|