2016-03-29 11 views
0

私は以下のコードを書いています(理解を目的としたものです)。メイン以外のint b;暫定的な定義を意味する。 main int b = 16の内部はローカル変数です。関数変数bの内部には、内部リンケージ(ファイルスコープ)があります。出力は16と0です。メモリが仮定義された変数に割り当てられるのは、初期化されたときだけです。だからここで私の質問は関数内にあり、printfはbの値を出力し、printfが呼び出されるとメモリが割り当てられますか?そのような場合は、最初にアクセスされたとき(初期化されているかアクセスされているかにかかわらず)、一時的に定義された変数にメモリが割り当てられていると言えますか?または私は間違っていますか?仮定義とメモリ割り当て

int b; 
int b; 
void f1(int a1); 
int main() 
{ 
    int b=16; 
    printf("b=%d\n",b); 
    f1(5); 
    return 0; 
} 

void f1(int a1) 
{ 
    printf("b = %d\n",b); 
} 

編集: は、より多くの明快さを追加: 私は関数内の変数がメインと異なっていることを承知しています。また、ローカル変数がスタックにあることにも注意してください。ここでの私の質問は、暫定的な定義に関するものです。 int bは2回宣言され、仮定義なのでC言語で受け入れられます。実際の定義の場合、複数の定義は許されないため、これは受け入れられません。暫定的な定義に関するいくつかの質問があります(About Tentative definition)。それらのうちの1つによると、 "Cには、同じ変数の複数の定義が一致し、多くとも1つに初期化子がある限り、複数の定義を可能にする特殊な"仮定義 "ルールがあります。定義を単一の定義に変換することができます。 私の質問を言い換えると:

変数は仮に定義されていても使用されていないとメモリは割り当てられますか? (コンパイラがコードを最適化しないと仮定します)。翻訳単位の終わりのように見えますが、上にリンクされている質問に従ってメモリが割り当てられます。 メモリが最初の時間(この場合はprintf文)で使用されている場合にのみ割り当てられるかどうか?

+0

'int b; int b;許されますか? :O – Downvoter

+0

* "仮の定義は、翻訳単位の終わりに達していて、識別子" * "のイニシャライザが定義されていない場合に完全な定義になります。したがって、最後の暫定的な定義は、グローバルスコープとゼロが初期化された実際の定義になりつつあります。 –

+0

@cad:それは同じです:はい。 1つで、これが真であるかどうかは不明です。 'typedef int it;それは標準で検索しなければならなかったが、とにかくこれを避けるだろう。 – Olaf

答えて

0

これらは2つの異なる変数です。

グローバルint b;では、プログラムがメモリに最初にロードされるときにメモリが割り当てられます。プログラムのグローバルメモリに割り当てられ、プログラムの任意のポイントから簡単にアクセスできます。

main()のローカルint b=16;は、main()ファンクションフレームでスタックに割り当てられます。その関数から直接アクセスすることしかできません。それ以外の場合は、main()が変数アドレスを渡すか、スタック上に複雑なポインタ演算を渡す必要があります。彼らは同じ名前を持っているので、あなたは、(いくつかの言語は、これを許可し、Cにはない)、この関数からグローバルなものを使用することはできませんが、それはそれであるので

ローカルbグローバルbを隠します。それらは異なる変数であり、名前を変更した場合、プログラムのバイナリ(実行された実際の命令)は変更されません。

0

int b;がゼロに初期化されている理由を説明しているこの回答を参照してください。

Does gcc automatically initialize static variables to zero?

メインでint b;がスタック上にあり、あなたの関数では16に設定スコープにあるのf1のみbシンボルは、ファイルスコープで宣言一つであり、それは標準が言うことだから、それはゼロに初期化されますそのはず。