はじめに
C++やC言語で、ポインタを使って構造体のメンバにアクセスするには、どうすればよいのでしょうか?
前回、構造体を指すポインタを宣言し、既存の変数のアドレスを代入する方法を学びました。今回は、そのポインタを通じて、指し示している先の構造体の個々のメンバ(idやnameなど)の値を読み書きするための、「アロー演算子 (->)」という特別な演算子について解説します。
アロー演算子 (->) を使ったサンプルコード
このコードは、Product(商品)という構造体の変数 item1 を作成し、ポインタ p_item が item1 を指すように設定します。その後、アロー演算子 -> を使って、ポインタ経由で item1 のメンバにアクセスします。
完成コード
#include <iostream>
#include <string>
// 「商品」構造体の定義
struct Product {
int id;
std::string name;
};
int main() {
// 1. 構造体の変数(実体)を作成
Product item1 = {101, "高機能マウス"};
// 2. 構造体を指すポインタを宣言し、item1のアドレスを代入
Product* p_item;
p_item = &item1;
// 3. アロー演算子(->)を使って、ポインタ経由でメンバの値を表示
std::cout << "--- アロー演算子(->)を使用 ---" << std::endl;
std::cout << "ID: " << p_item->id << std::endl;
std::cout << "商品名: " << p_item->name << std::endl;
// 4. アロー演算子(->)を使って、ポインタ経由でメンバの値を変更
p_item->id = 202;
p_item->name = "ワイヤレスキーボード";
// 5. 元の変数の値が変わっていることを確認
std::cout << "\n--- 変更後の元の変数の値 ---" << std::endl;
std::cout << "ID: " << item1.id << std::endl;
std::cout << "商品名: " << item1.name << std::endl;
return 0;
}
実行結果
--- アロー演算子(->)を使用 ---
ID: 101
商品名: 高機能マウス
--- 変更後の元の変数の値 ---
ID: 202
商品名: ワイヤレスキーボード
コードの解説
p_item->id
これが「アロー演算子」です。ハイフン - と大なり記号 > を組み合わせます。
ポインタ変数->メンバ名
この構文は、「ポインタ p_item が指し示している先にある構造体の、id というメンバ」にアクセスするという意味になります。
ポインタ p_item は item1 のアドレスを保持しているため、p_item->id は、結果的に item1.id と全く同じものを指します。実行結果が示すように、ポインタ経由で値を変更すると、元の変数 item1 の値も実際に変わります。
アロー演算子を使わない、もう一つの書き方
アロー演算子を使わずに、ポインタの基本である間接参照演算子(*)と、通常のメンバアクセス演算子(.)を組み合わせて同じことを表現することもできます。
(*ポインタ変数).メンバ名
// アロー演算子を使わない書き方(動作は同じ)
std::cout << "ID: " << (*p_item).id << std::endl;
std::cout << "商品名: " << (*p_item).name << std::endl;
*p_item: まず、ポインタp_itemが指すアドレスに間接参照して、item1という構造体そのものを取得します。(...):.演算子よりも*演算子の方が優先順位が低いため、先に間接参照を評価させるためにカッコが必要です。.id: 取得した構造体に対して、idメンバにアクセスします。
この (*p_item).id という書き方は、p_item->id と完全に等価です。しかし、見ての通り、アロー演算子 -> を使った方がはるかに直感的で、コードが読みやすいため、C++やC言語では、構造体のポインタ経由でのメンバアクセスには、ほぼ常にアロー演算子が使われます。
まとめ
今回は、構造体のポインタを通じて、そのメンバにアクセスするためのアロー演算子 -> について解説しました。
- 構造体を指すポインタからメンバにアクセスするには、アロー演算子 (
->) を使うのが一般的。 ポインタ->メンバは、(*ポインタ).メンバと等価であり、より簡潔な書き方。
このアロー演算子は、特に関数に構造体を渡す場面や、動的にメモリを確保して構造体を扱う場面など、ポインタが頻出する状況で必須の知識となります。
