構造体の中身を出力するプログラム…
#include <stdio.h> struct person { char name[20]; int age; }; void print_person(struct person *pp) { printf("Name: %s\n", pp->name); printf("Age: %d\n", pp->age); } int main(void) { struct person p = { "takehikom", 24 }; print_person(&p); return 0; }
何の変哲もないプログラムですが,昨日の演習で見かけて驚いたこととして,Nameの出力を
printf("Name: %s\n", pp);
と書いても,同じ出力になります.
少し考えてみれば,ここのppとpp->nameが同じアドレスになっていると想像できます.ただしアドレスは同じでも型は違うので,行儀のいい使い方とは言えません.実際,gcc -Wallでコンパイルすると,「警告: 初期化により、キャストなしでポインタから整数を作りました」という警告が出ました.
それと,nameが,構造体の中で先頭のメンバになっているのも,たまたま動く要因でして,これの順序を変えてから,「printf("Name: %s\n", pp);」とすると,何も出力しないとか,ゴミが出力されるとかいったことになります.上のプログラムで,nameとageの位置を交換する*1と,Nameには何も出ません.ageの初期値を,24から-1に変更すると,4バイトのゴミのあとに「takehikom」が出ました.リトルエンディアンだとか2の補数だとかを採用していることがうかがえます.
最後に,構造体を使ったプログラムを自在に書きたい人へのアドバイス:
- 「.」と「->」は2項演算子ですが,これらの演算子については,前後に空白を置かないのが慣例です.
- 構造体のポインタを引数にとる関数を書くとき,ポインタと分かる引数名にしましょう.構造体オブジェクトと同じ変数名にすると,混乱のもとです.
- 構造体を自分で定義したら,次に,その中身を見る(標準出力に出す)関数を定義しましょう*2.
*1:pの初期化も書き換える必要があります.