teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

11

修正

2019/10/17 04:44

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -41,7 +41,7 @@
41
41
  # 追記
42
42
 
43
43
  アセンブリコードが無いので、「その結果から推測されること」しか考察できません。スタックが使われていることも、そのスタックが後ろからプッシュされていることも推測です。
44
- float が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
44
+ double が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
45
45
  スタックに順に保存されていると推測するのが妥当でしょう。
46
46
 
47
47
  |変数|開始|終了|バイト数|

10

修正

2019/10/17 04:44

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -57,6 +57,8 @@
57
57
 
58
58
  しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化の影響はないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
59
59
 
60
- ターゲットが 64 ビットであればまた順序が変わったのではないと思い
60
+ ターゲットが 64 ビットであればまた順序が変わったかもしれせん
61
61
 
62
- そもそもスタックに一つ一つプッシュされたのではなく、計算でアドレスを決められた可能性の方が高いかもしれません。
62
+ そもそもスタックに一つ一つプッシュされたのではなく、計算でアドレスを決められた可能性の方が高いかもしれません。
63
+
64
+ 考察せよと改めて言われた場合、全てを推測で片付けたのではレポートとしてお粗末なものになるのではないでしょうか。

9

修正

2019/10/17 04:20

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -57,4 +57,6 @@
57
57
 
58
58
  しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化の影響はないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
59
59
 
60
- ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。
60
+ ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。
61
+
62
+ そもそもスタックに一つ一つプッシュされたのではなく、計算でアドレスを決められた可能性の方が高いかもしれません。

8

修正

2019/10/17 04:17

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  # 追記
42
42
 
43
- アセンブリコードが無いので、「その結果から推測されること」しか考察できません。
43
+ アセンブリコードが無いので、「その結果から推測されること」しか考察できません。スタックが使われていることも、そのスタックが後ろからプッシュされていることも推測です。
44
44
  float が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
45
45
  スタックに順に保存されていると推測するのが妥当でしょう。
46
46
 
@@ -55,6 +55,6 @@
55
55
 
56
56
  このように宣言された順にプッシュされているようです。
57
57
 
58
- しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化されてないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
58
+ しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化の影響はないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
59
59
 
60
60
  ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。

7

追記

2019/10/17 03:40

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -36,4 +36,25 @@
36
36
 
37
37
  **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**
38
38
 
39
- また今回はアドレスを出力させていますが、本番のコードでは必ずしも出力させるとは限りません。出力させるコードとさせないコードではコンパイル結果も変わるので、ソースコードをいじることでいじらなかったコードの状態を判断することはできません。
39
+ また今回はアドレスを出力させていますが、本番のコードでは必ずしも出力させるとは限りません。出力させるコードとさせないコードではコンパイル結果も変わるので、ソースコードをいじることでいじらなかったコードの状態を判断することはできません。
40
+
41
+ # 追記
42
+
43
+ アセンブリコードが無いので、「その結果から推測されること」しか考察できません。
44
+ float が 8 バイトで int が 4 バイトのメモリを使用してしるようです。
45
+ スタックに順に保存されていると推測するのが妥当でしょう。
46
+
47
+ |変数|開始|終了|バイト数|
48
+ |:--|:--|:--|:--|
49
+ |a|ffffcbfc|ffffcbff|4|
50
+ |b|ffffcbf8|ffffcbfb|4|
51
+ |x|ffffcbf0|ffffcbf7|8|
52
+ |y|ffffcbe8|ffffcbef|8|
53
+
54
+ このように割り当てられていると思います。まずはスタックポインタが ffffcc00 を指しているところに 4 バイトの a がプッシュされたので、スタックポインタは 4 減って ffffcbfc を指し、そこからの 4 バイトに a の内容が書き込まれます。次に 4 バイトの b がプッシュされたのでスタックポインタは 4 減って ffffcbf8 を指し、そこからの 4 バイトに b の内容が書き込まれます。
55
+
56
+ このように宣言された順にプッシュされているようです。
57
+
58
+ しかし、既に書いたようにこれは「たまたま」です。結果を見た上で「最適化されてないんだな、ローカル変数にはスタックを使ってるんだな」という想像はつきますが、常にこうなるわけではありません。
59
+
60
+ ターゲットが 64 ビットであればまた順序が変わったのではないかと思います。

6

修正

2019/10/17 03:24

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -30,7 +30,7 @@
30
30
  御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その直後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるため、アライメントを合わせるために前に置かれているのです。このアライメントというのは、たとえば 16 ビットのコンピューターなら 16 ビット毎、64 ビットなら 64 ビット毎にある境界のことで、データをこの境界に合わせて置かないと読み書きが遅くなります。
31
31
  ですから、char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
32
32
 
33
- そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量で不利になります。
33
+ そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、扱うデータによってはスタックの使用量で不利になります。
34
34
 
35
35
  また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
36
36
 

5

修正

2019/10/16 10:30

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -27,8 +27,8 @@
27
27
  a:6757FD6C, b:6757FD68, c:6757FD61, d:6757FD60, e:6757FD64
28
28
  ```
29
29
 
30
- 御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるために前に置かれているのです。
31
- char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
30
+ 御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるため、アライメントを合わせるために前に置かれているのです。このアライメントというのは、たとえば 16 ビットのコンピューターなら 16 ビット毎、64 ビットなら 64 ビット毎にある境界のことで、データをこの境界に合わせて置かないと読み書きが遅くなります。
31
+ ですから、char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
32
32
 
33
33
  そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
34
34
 

4

修正

2019/10/16 10:28

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -30,7 +30,7 @@
30
30
  御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるために前に置かれているのです。
31
31
  char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
32
32
 
33
- そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレスアドレス調整で対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
33
+ そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレス調整のみで対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
34
34
 
35
35
  また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
36
36
 

3

追記

2019/10/16 08:23

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -29,6 +29,9 @@
29
29
 
30
30
  御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるために前に置かれているのです。
31
31
  char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
32
+
33
+ そして、今回は後に置かれていますが、コンパイラによっては後に置かずアドレスアドレス調整で対応する場合もあるかもしれません。この場合、スタックの使用量では不利になります。
34
+
32
35
  また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
33
36
 
34
37
  **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**

2

追記

2019/10/16 08:17

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -31,4 +31,6 @@
31
31
  char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
32
32
  また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
33
33
 
34
- **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**
34
+ **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**
35
+
36
+ また今回はアドレスを出力させていますが、本番のコードでは必ずしも出力させるとは限りません。出力させるコードとさせないコードではコンパイル結果も変わるので、ソースコードをいじることでいじらなかったコードの状態を判断することはできません。

1

追記

2019/10/16 08:09

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -2,4 +2,33 @@
2
2
 
3
3
  [C言語のコードをアセンブラ出力を確認しながら最適化する | 組込みエンジニアの思うところ](https://nagayasu-shinya.com/cpp-optimize-assembler/)
4
4
 
5
- これは gcc ですが、コンパイラによってやり方は違います。また出力されるコードもコンパイラや最適化オプションによってそれぞれですから、同じコードなのに別のアドレスに割り当てられることもあります。
5
+ これは gcc ですが、コンパイラによってやり方は違います。また出力されるコードもコンパイラや最適化オプションによってそれぞれですから、同じコードなのに別のアドレスに割り当てられることもあります。
6
+
7
+ # 追記
8
+
9
+ ```C
10
+ #include <stdio.h>
11
+ #include <stdlib.h>
12
+
13
+ int main(int argc, char* argv[]) {
14
+ int a = 0;
15
+ int b = 0;
16
+ char c = 0;
17
+ char d = 0;
18
+ int e = 0;
19
+ printf("a:%X, b:%X, c:%X, d:%X, e:%X\n", (unsigned)&a, (unsigned)&b, (unsigned)&c, (unsigned)&d, (unsigned)&e);
20
+ return 0;
21
+ }
22
+ ```
23
+
24
+ Visual Studio の cl で上記ソースをコンパイルし、実行した結果です。
25
+
26
+ ```
27
+ a:6757FD6C, b:6757FD68, c:6757FD61, d:6757FD60, e:6757FD64
28
+ ```
29
+
30
+ 御覧の通り、一番最後に宣言された e が b と c の間にあります。c と d は 1 バイトなので、その後(スタックはアドレス番号が小さいほど後になります)に int 型を割り当てると速度的に不利になるために前に置かれているのです。
31
+ char 型が 4 つあった場合、対象コンピューターが 16 ビットなのか 64 ビットなのかによって配置も変わる可能性があります。
32
+ また、これはローカル変数なのでスタックに割り当てられていると推測されますが、必ずそうなるとは限りません。レジスタに割り当てられた場合、& でアドレスを取得できないので、アセンブリコード必須になります。
33
+
34
+ **ソースレベルで判断できるなど笑止千万です。そんなものは対象の環境によってもコンパイラによっても最適化によっても変わってくる話です。推測は可能ですが、それはあくまでも推測にすぎません。**