回答編集履歴

11

修正

2019/10/17 04:44

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -84,7 +84,7 @@
84
84
 
85
85
  アセンブリコードが無いので、「その結果から推測されること」しか考察できません。スタックが使われていることも、そのスタックが後ろからプッシュされていることも推測です。
86
86
 
87
- float が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
87
+ double が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
88
88
 
89
89
  スタックに順に保存されていると推測するのが妥当でしょう。
90
90
 

10

修正

2019/10/17 04:44

投稿

Zuishin
Zuishin

スコア28660

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

修正

2019/10/17 04:20

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -117,3 +117,7 @@
117
117
 
118
118
 
119
119
  ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。
120
+
121
+
122
+
123
+ そもそもスタックに一つ一つプッシュされたのではなく、計算でアドレスを決められた可能性の方が高いかもしれません。

8

修正

2019/10/17 04:17

投稿

Zuishin
Zuishin

スコア28660

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

追記

2019/10/17 03:40

投稿

Zuishin
Zuishin

スコア28660

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

修正

2019/10/17 03:24

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -62,7 +62,7 @@
62
62
 
63
63
 
64
64
 
65
- そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量で不利になります。
65
+ そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、扱うデータによってはスタックの使用量で不利になります。
66
66
 
67
67
 
68
68
 

5

修正

2019/10/16 10:30

投稿

Zuishin
Zuishin

スコア28660

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

修正

2019/10/16 10:28

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -62,7 +62,7 @@
62
62
 
63
63
 
64
64
 
65
- そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレスアドレス調整で対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
65
+ そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
66
66
 
67
67
 
68
68
 

3

追記

2019/10/16 08:23

投稿

Zuishin
Zuishin

スコア28660

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

追記

2019/10/16 08:17

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -65,3 +65,7 @@
65
65
 
66
66
 
67
67
  **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**
68
+
69
+
70
+
71
+ また今回はアドレスを出力させていますが、本番のコードでは必ずしも出力させるとは限りません。出力させるコードとさせないコードではコンパイル結果も変わるので、ソースコードをいじることでいじらなかったコードの状態を判断することはできません。

1

追記

2019/10/16 08:09

投稿

Zuishin
Zuishin

スコア28660

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
+ **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**