メモリは,0か1を書き並べる場所である.メモリ空間という. 0/1を横一列に並べてみると,メモリの大きさがわかる.
CPUは,メモリの一部分しか読み書きできない. したがって,メモリ空間のどの場所を読み書きするのかを指定しないといけない.
1ビットごとに場所を決めることは効率が悪いので, 8ビットを1バイトと呼び,1バイトごとにメモリ空間上の番地が決められている. これをアドレスという.
たとえば,102,478 番地を起点に,"abc" という文字列を格納すると,以下の図のようになる.
102,478番地から102,481番地は,"abc"(NULL文字含む)のためのメモリ空間であるが,それ以外の部分は未知である.したがって,メモリの読み書きは,何番地から何番地までを使って良いのか,十分に注意を払う必要がある.
char s[4] により配列変数を宣言すると,適切な番地を起点に,上の図のようにメモリ空間が使われている.
配列変数の宣言の時の [4] は,起点番地を含めて幾つまでを使うか,配列の大きさを表す.
配列変数への読み書きの時の [1]は,配列番号といい,起点番地からの相対的な番地を表す.したがって,C言語のプログラマは,起点番地の数字を意識する必要はなく,s[0]='a'; s[1]='b'; s[2]='c'; s[3]='\0'; という操作により文字列を格納すれば良い.
char *p により文字へのポインタ型変数を宣言すると,変数 p には,番地の数字を直接代入することになる.したがって,上の図において,p=102478 と代入し,*p='a' とすると,その番地の 0/1 を「0110001」とすることができ,'a'を代入したことになる.
ポインタ型変数に +1 をすると,番地の数値を 1 データぶんだけ次の番地を指すようになる.char 型の場合,1バイトぶんの大きさである.したがって,char 型へのポインタ変数に +1 をすると番地番号も1つだけ増える.しかし,int 型の場合 4 バイトぶんの大きさであるので,int型へのポインタ変数に +1 をすると番地番号は4つ増える.
しかしながら,C言語のプログラマは,番地番号が4つ増えるのか1つ増えるのかは,気にする必要はない.char *p や int *q などのように,プログラム上では,char や int という意味でポインタを使うので,コンパイラーが+4なのか+1なのかを判断するからである.
char *s; s = (char *)malloc(sizeof(char)*(10));
/* prac0501.c */ #include <stdio.h> #include <string.h> char *zenkakurev(const char str[]) { ここにプログラムを書く } main() { char str1[BUFSIZ]; char *str2; fgets(str1,BUFSIZ,stdin); if(str1[strlen(str1)−1] == ’\n’ ) str1[strlen(str1)−1] = ’\0’; str2 = zenkakurev(str1); printf(”%s\n”,str2); free(str2); }