下記のプログラムを実行するとどのような出力が得られるかわかりますか?
# include <stdio.h>
typedef struct {
int a;
int b;
} t_structure;
int main(void){
t_structure structure;
structure.a = 5;
t_structure *p_structure = &structure;
printf("(1)structure.a...%d\n", structure.a); //(1)
printf("(2)p_structure->a...%d\n", p_structure->a); //(2)
printf("(3)(*p_structure).a...%d\n", (*p_structure).a); //(3)
printf("(4)p_structure[0].a...%d\n", p_structure[0].a); //(4)
}
このプログラムを実行すると以下のような出力が得られます.
(1)structure.a...5
(2)p_structure->a...5
(3)(*p_structure).a...5
(4)p_structure[0].a...5
(1)~(4)のすべてで構造体のメンバ変数a
が保持する値にアクセス出来ています.
つまり,(1)~(4)はすべて同じ意味です.
なぜ同じ意味になるのかを説明することが出来ますか?
この記事ではその理由を説明していきます.
(1)structure.a##
これは簡単ですね.
構造体のメンバにアクセスしたいときは.
を使用します.
構造体変数.メンバ
と書くことでメンバにアクセス出来ます.
(2)p_structure->a##
これは構造体へのポインタを使ったことがある人ならわかると思います.
p_structure
は構造体変数structure
へのポインタになっています.
構造体へのポインタを使って,メンバにアクセスするためにはアロー演算子->
を使用します.
構造体へのポインタ->メンバ
と書くことでメンバにアクセス出来ます.
(3)(*p_structure).a##
これは(2)をなんとなく使っていた人はわからないかもしれません.
ポインタが保持しているアドレスにアクセスするためには*
を使用します.
*p_structureとすることで
p_structureが保持している
structureにアクセスしています.つまり,
*p_structureと
structure`は等価です.
ここまでわかれば,(3)が(1)と同じ意味になるのは理解出来るでしょう.
また,(2)で使用したアロー演算子はこの書き方を簡単に書くための演算子です.
(4)p_structure[0].a##
これを理解できる人はポインタへの理解が深い人でしょう.
*p_structure
はp_structure[0]
とも書き換えることが出来ます.
p_structure[0]
は*(p_structure + 0)
を簡単に書くための記法だからです.
これがわかれば(4)が(3)と同じ意味になる理由が理解出来ると思います.
終わりに##
さて,ここまで(1)~(4)が同じ意味になることを説明してきました.
では,構造体へのポインタからメンバ変数を参照したい場合,どれを使うのがいいのでしょうか?
僕は,(2)が一番良いと思います.(2)が最も簡潔に書けるからです.
(3)や(4)は(2)をこのように書き換えられるよという程度のものです.聞かれて説明出来る必要はあると思いますが,実際に書く必要はないと思います.