C/C++ ポインタ入門 > ポインタと構造体
Nobuhide Tsuda
Apr-2014
ポインタと構造体
- 構造体とは、関連する複数のデータをひとつにまとめ、扱いやすくするためのもの。
- 例えば、人間であれば、名前、年齢、電話番号などのデータをひとまとまりにした人間構造体を定義できる。
- どのようなデータメンバを持たせるかは、構造体をどう使用したいかに依存する。
- 関数にひとまとまりのデータを渡す場合、構造体にして、ポインターを渡すことがよくある。
それぞれのデータを引数に記述すると、引数の数が多くなり文書性や低下するなどの弊害があるからだ。
func("okada", 24, 180, 70, true); // 引数に各データを指定した場合
↓ 構造体化により、関数コール時の引数をスッキリ
struct Person {
std::string m_name; // 名前
int m_age; // 年齢
int m_height; // 身長
int m_wait; // 体重
.....
};
Person *ptr = new Person("okada", 24, 180, 70);
func(ptr, true); // 関数コール時の引数がスッキリしたでしょ
単方向・双方向リストはノート構造体を定義し、必要に応じてノードを動的に生成破棄する。
ノードにアクセスするときは、ポインタを使いノードのデータを間接的に参照する。
ポインタと構造体の組み合わせは非常によく使用する、応用範囲の広いテクニックだぞ。
構造体宣言
- 構造体は「struct」で始め、構造体・クラス名 { メンバ宣言... }; という書式で宣言する。
struct Hoge
{
int m_data; // データメンバ
int m_foo; // データメンバ
.....
};
古いCでは typedef struct タグ名 { メンバ変数宣言… } 構造体名; という書き方をする。
- この書き方は現在でも可能であるが、冗長なので、使用しない方がよいと考える。
演習問題:
- int 型の x座標(m_x)、y 座標(m_y)をメンバに持つ Point 構造体を宣言しなさい。
- int 型の値(m_value)と次のノードへのポインタ(m_next)をメンバに持つ Node 構造体を宣言しなさい。
生成と破棄
C の場合
- 構造体名をTとすると、T *ptr = (T *)malloc(sizeof(T)); で構造体を生成し、そのアドレスを ptr に格納する。
- malloc() で生成した構造体を破棄する場合は free(ptr); を実行する。
- malloc() で生成した場合、データは不定なので、自分で初期化する必要がある。
Hoge *ptr = (Hoge *)malloc(sizeof(T));
ptr->m_data = 1;
ptr->m_foo = 2;
...
free(ptr);
calloc(size_t) はアロケートしたメモリを0クリアすることが保証されている。データを全て0に初期化したい場合は、この関数を使うとよい。
C++ の場合
- 構造体名をTとすると、T *ptr = new T; で構造体を生成する。
- ptr = new T(); と丸括弧を記述してもよい。
- 単に T obj; と記述すると、現在のスコープ内で、構造体が生成される。
- 注意: T obj(); と記述すると、T 型を返す関数宣言と見なされるので、この場合は空の丸括弧「()」を付加してはいけない。
- ptr = new T; で生成したオブジェクトを破棄する場合は delete ptr; を記述する。
- データの初期化は malloc() の場合と同じように、生成後に行う。
- 実は構造体でもクラスと同じようにコンストラクタを定義し、そこでメンバ変数を初期化することができる。
- その方法は次章「ポインタとクラス」で説明する。
演習問題:
- 前節演習問題の Point 構造体を new/delete または malloc/free 使って生成、破棄するコードを書きなさい。
- 前節演習問題の Node 構造体を new/delete または malloc/free 使って生成、破棄するコードを書きなさい
メンバの参照
- ポインタ ptr が指す先の構造体のデータメンバは「ptr->メンバ名」で参照する。
- ptr->メンバ名 = 式; でメンバに値を代入することもできる。
- (*ptr).メンバ名 で参照してもよい。
- 実態とポインタで、メンバを参照するための演算子が異なるのは C の文法上の不備
演習問題:
- Point 構造体へのポインタを引数にとり、座標値を表示する関数 void print(Point *ptr); を実装しなさい。
- Point 構造体へのポインタ、x座標、y座標を引数にとり、座標値を設定する関数 void setXY(Point *ptr, int x, int y) を実装しなさい。
前:ポインタへのメモリ割り当て
|上:C/C++ ポインタ入門
|次:ポインタとクラス