回答編集履歴
11
修正
test
CHANGED
@@ -84,7 +84,7 @@
|
|
84
84
|
|
85
85
|
アセンブリコードが無いので、「その結果から推測されること」しか考察できません。スタックが使われていることも、そのスタックが後ろからプッシュされていることも推測です。
|
86
86
|
|
87
|
-
|
87
|
+
double が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
|
88
88
|
|
89
89
|
スタックに順に保存されていると推測するのが妥当でしょう。
|
90
90
|
|
10
修正
test
CHANGED
@@ -116,8 +116,12 @@
|
|
116
116
|
|
117
117
|
|
118
118
|
|
119
|
-
ターゲットが 64 ビットであればまた順序が変わった
|
119
|
+
ターゲットが 64 ビットであればまた順序が変わったかもしれません。
|
120
120
|
|
121
121
|
|
122
122
|
|
123
123
|
そもそもスタックに一つ一つプッシュされたのではなく、計算でアドレスを決められた可能性の方が高いかもしれません。
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
考察せよと改めて言われた場合、全てを推測で片付けたのではレポートとしてお粗末なものになるのではないでしょうか。
|
9
修正
test
CHANGED
@@ -117,3 +117,7 @@
|
|
117
117
|
|
118
118
|
|
119
119
|
ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
そもそもスタックに一つ一つプッシュされたのではなく、計算でアドレスを決められた可能性の方が高いかもしれません。
|
8
修正
test
CHANGED
@@ -82,7 +82,7 @@
|
|
82
82
|
|
83
83
|
|
84
84
|
|
85
|
-
アセンブリコードが無いので、「その結果から推測されること」しか考察できません。
|
85
|
+
アセンブリコードが無いので、「その結果から推測されること」しか考察できません。スタックが使われていることも、そのスタックが後ろからプッシュされていることも推測です。
|
86
86
|
|
87
87
|
float が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
|
88
88
|
|
@@ -112,7 +112,7 @@
|
|
112
112
|
|
113
113
|
|
114
114
|
|
115
|
-
しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化
|
115
|
+
しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化の影響はないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
|
116
116
|
|
117
117
|
|
118
118
|
|
7
追記
test
CHANGED
@@ -75,3 +75,45 @@
|
|
75
75
|
|
76
76
|
|
77
77
|
また今回はアドレスを出力させていますが、本番のコードでは必ずしも出力させるとは限りません。出力させるコードとさせないコードではコンパイル結果も変わるので、ソースコードをいじることでいじらなかったコードの状態を判断することはできません。
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
# 追記
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
アセンブリコードが無いので、「その結果から推測されること」しか考察できません。
|
86
|
+
|
87
|
+
float が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
|
88
|
+
|
89
|
+
スタックに順に保存されていると推測するのが妥当でしょう。
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|変数|開始|終了|バイト数|
|
94
|
+
|
95
|
+
|:--|:--|:--|:--|
|
96
|
+
|
97
|
+
|a|ffffcbfc|ffffcbff|4|
|
98
|
+
|
99
|
+
|b|ffffcbf8|ffffcbfb|4|
|
100
|
+
|
101
|
+
|x|ffffcbf0|ffffcbf7|8|
|
102
|
+
|
103
|
+
|y|ffffcbe8|ffffcbef|8|
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
このように割り当てられていると思います。まずはスタックポインタが ffffcc00 を指しているところに 4 バイトの a がプッシュされたので、スタックポインタは 4 減って ffffcbfc を指し、そこからの 4 バイトに a の内容が書き込まれます。次に 4 バイトの b がプッシュされたのでスタックポインタは 4 減って ffffcbf8 を指し、そこからの 4 バイトに b の内容が書き込まれます。
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
このように宣言された順にプッシュされているようです。
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化されてないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。
|
6
修正
test
CHANGED
@@ -62,7 +62,7 @@
|
|
62
62
|
|
63
63
|
|
64
64
|
|
65
|
-
そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量で
|
65
|
+
そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、扱うデータによってはスタックの使用量で不利になります。
|
66
66
|
|
67
67
|
|
68
68
|
|
5
修正
test
CHANGED
@@ -56,9 +56,9 @@
|
|
56
56
|
|
57
57
|
|
58
58
|
|
59
|
-
御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるために前に置かれているのです。
|
59
|
+
御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その直後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるため、アライメントを合わせるために前に置かれているのです。このアライメントというのは、たとえば 16 ビットのコンピューターなら 16 ビット毎、64 ビットなら 64 ビット毎にある境界のことで、データをこの境界に合わせて置かないと読み書きが遅くなります。
|
60
60
|
|
61
|
-
char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
|
61
|
+
ですから、char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
|
62
62
|
|
63
63
|
|
64
64
|
|
4
修正
test
CHANGED
@@ -62,7 +62,7 @@
|
|
62
62
|
|
63
63
|
|
64
64
|
|
65
|
-
そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス
|
65
|
+
そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
|
66
66
|
|
67
67
|
|
68
68
|
|
3
追記
test
CHANGED
@@ -60,6 +60,12 @@
|
|
60
60
|
|
61
61
|
char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
|
62
62
|
|
63
|
+
|
64
|
+
|
65
|
+
そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレスアドレス調整で対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
|
66
|
+
|
67
|
+
|
68
|
+
|
63
69
|
また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
|
64
70
|
|
65
71
|
|
2
追記
test
CHANGED
@@ -65,3 +65,7 @@
|
|
65
65
|
|
66
66
|
|
67
67
|
**ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
また今回はアドレスを出力させていますが、本番のコードでは必ずしも出力させるとは限りません。出力させるコードとさせないコードではコンパイル結果も変わるので、ソースコードをいじることでいじらなかったコードの状態を判断することはできません。
|
1
追記
test
CHANGED
@@ -7,3 +7,61 @@
|
|
7
7
|
|
8
8
|
|
9
9
|
これは gcc ですが、コンパイラによってやり方は違います。また出力されるコードもコンパイラや最適化オプションによってそれぞれですから、同じコードなのに別のアドレスに割り当てられることもあります。
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
# 追記
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
```C
|
18
|
+
|
19
|
+
#include <stdio.h>
|
20
|
+
|
21
|
+
#include <stdlib.h>
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
int main(int argc, char* argv[]) {
|
26
|
+
|
27
|
+
int a = 0;
|
28
|
+
|
29
|
+
int b = 0;
|
30
|
+
|
31
|
+
char c = 0;
|
32
|
+
|
33
|
+
char d = 0;
|
34
|
+
|
35
|
+
int e = 0;
|
36
|
+
|
37
|
+
printf("a:%X, b:%X, c:%X, d:%X, e:%X\n", (unsigned)&a, (unsigned)&b, (unsigned)&c, (unsigned)&d, (unsigned)&e);
|
38
|
+
|
39
|
+
return 0;
|
40
|
+
|
41
|
+
}
|
42
|
+
|
43
|
+
```
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
Visual Studio の cl で上記ソースをコンパイルし、実行した結果です。
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
```
|
52
|
+
|
53
|
+
a:6757FD6C, b:6757FD68, c:6757FD61, d:6757FD60, e:6757FD64
|
54
|
+
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるために前に置かれているのです。
|
60
|
+
|
61
|
+
char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
|
62
|
+
|
63
|
+
また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
**ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**
|