概要
このまとめは個人的に C++ における配列とポインタの扱いについて忘れていた部分や新たに知ったことについてまとめたいと思います。
1. char型のアドレスの出力
ある変数のアドレスを取得したい時は基本的に変数名の前にアンパサンド'&'をかけば、その変数のアドレスを出力することが出来ます。
int x = 2014;
cout << "Address: " << &x << endl;
Address: 0x7fff5c34998c
ところが、char型の場合単純にアンパサンドをつけても、
char ch = 'c';
cout << "Address: " << &ch << endl;
Address: c?i?T?
うまく表示されません。これは、char型のアドレスを表示しようとすると文字列を表示しようとしてしまうのが原因だと考えられます。文字列を表示するときもcharの先頭アドレスを与えてあげる必要があるので、それと間違ってしまうんですね。なので、
char ch = 'c';
cout << "Address: " << (void*) &ch << endl;
Address: 0x7fff5337498f
出力する際に(void*)にキャストしてあげることでうまく表示させることが出来ます。
2. 文字列リテラルとポインタ
文字列リテラルはダブルコーテーション""で囲むことにより利用することが出来ます。そして、この表現によって文字列の先頭アドレスを取得することが出来ます。
const char *ch = "literal";
cout << "Address: " << (void*) &ch << endl;
Address: 0x7fff5fbff888
文字列リテラルが文字列の先頭アドレスを返すということはポインタのような操作ももちろん可能です。つまり、
cout << "ABCの二つ目の文字は: " << *("ABC" + 1) << endl;
ABCの二つ目の文字は: B
こんな直接的な書き方も出来てしまいます。
3. ポインタの配列
ポインタの配列に関して少しややこしいと思った部分があったのでまとめます。
ポインタの配列は宣言するとき注意する必要があります。ちょっとした違いが意味の違うポインタの宣言をしてしまいます。
int *p[5]; // int型へのポインタの要素数5の配列
int (*p2)[5]; // 要素数5の配列へのポインタ
// p はint型へのポインタを5つ格納できる配列
int values[] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
p[i] = &values[i];
}
cout << "---------- p: output -------------" << endl;
for (int i = 0; i < 5; i++) {
cout << *p[i] << " ";
}
cout << endl;
// p2 は2次元配列
int (*p2)[5];
int array[3][5] = {
{11, 12, 13, 14, 15},
{21, 22, 23, 24, 25},
{31, 32, 33, 34, 35}
};
p2 = &array[0]; // 要素数5の配列のアドレスを格納できる
cout << "---------- p2: output -------------" << endl;
for (int i = 0; i < 5; i++) {
cout << (*p2)[i] << " ";
}
cout << endl;
---------- p: output -------------
1 2 3 4 5
---------- p2: output -------------
11 12 13 14 15
*や[]の演算子の優先順位の関係で、宣言する際に括弧を付けるつけないでポインタの意味が変わってしまうので気をつけましょう。
ここに詳しく書いてあるので参考までに -> 2次元配列とポインタ