質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

6回答

3357閲覧

関数内のローカル変数のメモリの割り当てについて

maikeru

総合スコア68

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2018/11/07 12:03

関数内のローカル変数が割り当てられるメモリのアドレスを見るために次のC言語のプログラムを実行したら実行結果が次のようになりました。

a = 0061FF20
b = 0061FF24
c = 0061FF28
buf1 = 0061FF0B
buf2 = 0061FF01

私はプログラムからスタックには
関数の戻りアドレス、c、b、a、buf1、buf2
の順にPUSHされると思っていたのですが
0061FF10~0061FF19
の部分のメモリに変数が割り当てられていません。この部分には何か格納されているのでしょうか?

C

1#include <stdio.h> 2 3void func(int a, int b, int c){ 4 char buf1[5]; 5 char buf2[10]; 6 7 printf("a = %p\n", &a); 8 printf("b = %p\n", &b); 9 printf("c = %p\n", &c); 10 printf("buf1 = %p\n", buf1); 11 printf("buf2 = %p\n", buf2); 12} 13 14int main(void){ 15 func(1, 2, 3); 16 return 0; 17}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

直接的な回答ではないですが、結果の数字は パソコンや使用するコンパイラによって異なります。
指定された変数をどの番号の目盛りに割り当てるのかは、コンパイラが自動的に決めるからです。
さらに言うと、その値もOSの仮想メモリ機能によって変化します。

投稿2018/11/07 12:22

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

適当に調べてみました。
gcc version 7.3.0 (Rev2, Built by MSYS2 project)
Target: i686-w64-mingw32

c

1#include <stdio.h> 2 3int main(void); 4 5void func(int a, int b, int c){ 6 char buf1[5]; 7 char buf2[10]; 8 9 puts("----------------------------------------------"); 10 printf("(&a)[-1]=%p\n", (&a)[-1]); 11 printf(" =main+0x%04x\n",((&a)[-1])-(int)main); 12 printf("call to = %d\n", ((int*)((&a)[-1]))[-1]); 13 printf("func-return_ptr= %d\n", (char*)func - (char*)((&a)[-1])); 14 printf("(&a)[-2]=%p\n", (&a)[-2]); 15 printf("&a-2 = %p\n", &a-2); 16 printf("(&a)[-3]=%p\n", (&a)[-3]); 17 printf("&a-3 = %p\n", &a-3); 18 printf("(&a)[-4]=%p\n", (&a)[-4]); 19 printf("&a-4 = %p\n", &a-4); 20 printf("a = %p\n", &a); 21 printf("b = %p\n", &b); 22 printf("c = %p\n", &c); 23 printf("buf1 = %p\n", buf1); 24 printf("buf2 = %p\n", buf2); 25 if(a == 1) 26 func(a+1,b,c); 27} 28 29int main(void){ 30 func(1, 2, 3); 31 return 0; 32}

結果が

---------------------------------------------- (&a)[-1]=00401761 =main+0x002a call to = -417 func-return_ptr= -417 (&a)[-2]=0028FEE8 &a-2 = 0028FEC8 (&a)[-3]=008717AC &a-3 = 0028FEC4 (&a)[-4]=0000001E &a-4 = 0028FEC0 a = 0028FED0 b = 0028FED4 c = 0028FED8 buf1 = 0028FEBB buf2 = 0028FEB1 ---------------------------------------------- (&a)[-1]=00401734 =main+0xfffffffd call to = -372 func-return_ptr= -372 (&a)[-2]=0028FEC8 &a-2 = 0028FE98 (&a)[-3]=FFFFFFFE &a-3 = 0028FE94 (&a)[-4]=14CDF076 &a-4 = 0028FE90 a = 0028FEA0 b = 0028FEA4 c = 0028FEA8 buf1 = 0028FE8B buf2 = 0028FE81

小さい
buf2
buf1
不明
不明
スタックフレームポインタ
戻り先アドレス
a
b
c
大きい

ですね

不明箇所は再帰して同箇所で読んでるのにも関わらず不定なので、未使用もしくはレジスタの退避のようです。

投稿2018/11/08 00:43

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

この部分には何か格納されているのでしょうか?

こういう事を知りたいなら、コンパイラが生成したアセンブリコードを読むことです。
gcc なら -S オプション付きでコンパイルすると、foo.c から foo.s が作られます。
gcc -S foo.c

スタックには関数の戻りアドレス、c、b、a、buf1、buf2 の順にPUSHされると思っていた

ことの、どこに誤りがあるか、自分で確認できるでしょう。
Enjoy!

投稿2018/11/07 21:27

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

その考えで間違いないと思います。ただ、スタックの上と下を逆に考えていると思います。

もっとも、これはC言語のルールではありません。コンパイラ次第です。詳しく知りたいならば、アセンブラ出力するとかすれば中身がわかります。

投稿2018/11/07 12:17

編集2018/11/07 12:18
HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

コンパイラ、言語処理系によっては
アセンブラとのI/F
として説明されているものがあります。
アセンブラからC言語の関数を呼ぶ場合、逆に、C言語からアセンブラを呼び出す場合に、
スタックをどのように扱うか、の説明です。

お使いの処理系の説明書を見てください。

投稿2018/11/08 01:33

nob.

総合スコア711

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

0061FF10~0061FF19

は、0061FF10~0061FF1F の間違いでしょうね。16バイトですね。
関数から親への戻りアドレスと、親のフレームポインタ、各8バイト(64bit環境だとして)だと思います。

投稿2018/11/07 12:48

otn

総合スコア84421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問