
char 型ポインタ変数を使って、文字列を扱ってみましょう。
C 言語で文字列がメモリの中でどのように扱われているかを知っておくことで、 例えば、char 型配列としてメモリ上に読み込んだマップデータやシナリオデータといったゲームデータなどの取扱いを理解しやすくなります。
char *playername="planc";
char 型のポインタに対して、ダブルクオーテーションで囲んだ文字列を代入する式を書くことで 文字列を変数で扱うことができます。
次のソースコードでは、char型のポインタ変数 playername に、文字列「planc」を代入しています。
#include <stdio.h>
int main(){
char *playername="planc";
printf("プレイヤーの名前 = %s \n", playername);
printf("変数 playername の指すメモリアドレス = %d \n", playername);
printf("playername[0] アドレス = %d, 文字 = %c, 数字 = %d \n", &playername[0], playername[0], playername[0] );
printf("playername[1] アドレス = %d, 文字 = %c, 数字 = %d \n", &playername[1], playername[1], playername[1] );
printf("playername[2] アドレス = %d, 文字 = %c, 数字 = %d \n", &playername[2], playername[2], playername[2] );
printf("playername[3] アドレス = %d, 文字 = %c, 数字 = %d \n", &playername[3], playername[3], playername[3] );
printf("playername[4] アドレス = %d, 文字 = %c, 数字 = %d \n", &playername[4], playername[4], playername[4] );
printf("playername[5] アドレス = %d, 文字 = %c, 数字 = %d \n", &playername[5], playername[5], playername[5] );
}
実行すると下の結果となりました。
プレイヤーの名前 = planc
変数 playername の指すメモリアドレス = 4231168
playername[0] アドレス = 4231168, 文字 = p, 数字 = 112
playername[1] アドレス = 4231169, 文字 = l, 数字 = 108
playername[2] アドレス = 4231170, 文字 = a, 数字 = 97
playername[3] アドレス = 4231171, 文字 = n, 数字 = 110
playername[4] アドレス = 4231172, 文字 = c, 数字 = 99
playername[5] アドレス = 4231173, 文字 = , 数字 = 0
3 行目で、先ほど「char型のポインタ変数 playername に文字列を代入している」と書いた処理が実行されます。
char *playername="planc";
char型ポインタ変数と、char型変数は何が違うのでしょうか。
見た目上の違いは*が変数の直前についているだけですね。
char 型は 1バイト(ASCIIコード表での 1 文字ぶん)しか入らないはずですが、どのように文字列を保存しているのでしょうか。
ではでは、仕組みを確認してきましょう。
まず、"planc" という文字列は、実際には
planc\0
というデータとして、メモリ上に確保されます。
ダブルクオーテーションで囲んだ文字列は、最後に文字列のデータがココで終わるよ、ということを表す '\0' がつくというルールとなっているためです。 この処理は自動的にコンパイラがやってくれます。
なお、この '\0' が無理やり取っ払ったりすると、どこが終わりかわからなくなってしまい、バグの原因となります。
char *playername="planc";
この行では、変数の宣言と初期化を同時に行っています。
ちょっと復習になりますが、 宣言とは、××型の〇〇という変数を使いますよ、ということです。 この行では、「char *playername」 部分が宣言です。
初期化とは、変数の中身の最初の値をセットすることです。 この行では 「変数="planc"」の部分が初期化です。
この変数と初期化では、文字列 "planc" のデータの先頭の 1 文字である「p」 の文字データが入っているメモリアドレスを、playername というポインタ変数にセットする、ということを行っています。
変数の宣言と初期化を2行に分けて、下のようにも書けます。
char *playername;
playername = "planc";
つまり、playername というポインタ変数は、文字列そのもののデータを保持しているのではなく、 文字列の先頭部分へのメモリアドレスを持っているだけなのです。
playername に、文字列の頭へのメモリアドレスが入っている状態となり、 次の 4 行目では、printf 関数でコンソール上で変数の内容を出力しています。
printf("player name is %s \n", playername);
printf の第一引数で %s を指定すると、第二引数以降に指定した 変数の内容を書式に従って表示します。ここでは、 %s と書いた部分に playername の中身が表示されます。
printf の %s を playername の中身で置き換える処理は、
渡された変数 playername のメモリアドレスの中身を順番に取得していき '\0' が見つかったら、 表示する文字の終わりに到達したと判断して置き換え終了とする。
という処理を実施しています。
プログラムを実行した時、文字列 "planc" がメモリ上でどのように扱われたか、 どのようにアクセスできるかを対応表にしたものです。
文字 | 'p' | 'l' | 'a' | 'n' | 'c' | '\0' |
---|---|---|---|---|---|---|
データ | 112 | 108 | 97 | 110 | 99 | 0 |
メモリアドレス | 4231168 | 4231169 | 4231170 | 4231171 | 4231172 | 4231173 |
playername | [0] | [1] | [2] | [3] | [4] | [5] |
メモリアドレスが 1 文字につき 1 (バイト)隣り合って保存されているのがわかります。
今回はここまでです!おつかれさまでした。
更新日 | 更新内容 |
---|---|
更新なし |
コメント、ありがとうございます。
ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。
Twitter:@NodachiSoft_jpお名前:以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください
お名前: