回答編集履歴
1
いくつか言い回しを修正
test
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
関数に構造体(構造体変数)を渡すことはでき
|
1
|
+
関数に構造体(構造体変数)を引数で渡すことはできるので、printf() に構造体を渡すこともできなくないでしょう。
|
2
|
-
でも、構造体を渡せば全てのメンバ変数を出力する、という仕様はありません。
|
2
|
+
でも、構造体を渡せば全てのメンバ変数を出力する、という仕様は printf() にありません。
|
3
3
|
|
4
4
|
私の説明に必要な部分を簡略化したコードで示します。
|
5
5
|
```C
|
@@ -34,20 +34,20 @@
|
|
34
34
|
11, 3.141500
|
35
35
|
sizeof animal = 16
|
36
36
|
```
|
37
|
-
と、正しく(?)表示されました。質問者のコンパイラも64bit版だと思います。
|
37
|
+
と、正しく(?)表示されました。なので質問者のコンパイラも64bit版だと思います。
|
38
38
|
|
39
39
|
構造体 animal のサイズも表示させました。どちらも16です。
|
40
|
-
普通
|
40
|
+
普通 sizeof int は4,sizeof doubleは8で合計12と思いきや、16です。
|
41
41
|
メンバ変数 eye と weight の間に4バイトの隙間があるのです。
|
42
42
|
|
43
|
-
さて、関数に構造体を渡そうとすれば、**引数の領域**に
|
43
|
+
さて、関数に構造体を渡そうとすれば、**引数の領域**に構造体分(この場合は16バイト)のメモリが割当てられ、そこに animal の値を代入し、それが関数=この場合は printf()に渡ります。
|
44
44
|
|
45
45
|
しかし printf() は animal 構造体の定義を知りませんから、隙間があることも知りません。"%d, %f\n" という文字列(変換指定)に従って、引数領域を表示するだけです。
|
46
46
|
|
47
|
-
その結果、32bit版では隙間部分を %f で表示
|
47
|
+
その結果、32bit版では隙間部分を %f で表示することになってしまい全く違う値が表示されたのです。こういう事を、巷ではコンパイラの未定義動作とか実装依存とか呼んでるようです。ある環境でうまくいったとしても他所でうまくいく保証の無い事なので、やっちゃいけないことなんです。
|
48
48
|
|
49
49
|
では64bitコンパイラでうまくいったのはなぜか。
|
50
|
-
32bitコンパイラと64bitコンパイラでは引数
|
50
|
+
32bitコンパイラと64bitコンパイラでは引数領域の構造に違いがあるのです。それが**たまたま上手くいった**理由と関係しています。その違いを具体的に説明するのは、面倒なのでパスしたい。
|
51
51
|
|
52
52
|
ご注意。隙間ができるかどうかもコンパイラ次第、隙間ができない場合もあります。
|
53
53
|
|