なぜグローバル変数を初期化する必要がありますか?

まず、初期化ルールのセクション

なぜ初期化を説明する前に、最初に後で使用するために、C言語の初期化ルールを述べました。
私たちは、このように初期化される配列で使用することができます:

チャー BUF [ 10 ] = { 0 }。

次いで  チャー BUF [ 10 ] = { 1 }、各アレイの各要素は、1つのアウトに初期化されていませんか?

初期化要素を指定するときに実際には、コンパイラの特性に応じて、配列要素の総数よりも少ない素子数場合、他の要素がゼロに初期化されます。

私たちは、コードの一部を確認するために、この機能を使用することができます。

1つの#include <stdio.hの>
 2  
3  INT メイン()
 4  {
 5    チャー BUF [ 10 ] = { 1 }。
6  
7    戻り 0 8 }

分解は、次のように:

1  <メイン>:
 2    プッシュ {FP} (STRのFP、[SP、#-4]!)
3    加算 FP、SP、#0 
4    サブ SP、SP、#20 
5    サブ R3、FP、#16 
6    のMOV R2、#0 
7つの   STR R2、[R3]
 8つの   STR R2、[R3、#4 ]
 9つの    STRH R2、[R3、#8 ]
 10の   MOV R3、#は1 
11    のSTRB R3、[FP、# - 16 ]
 12    のMOV R3、#0 
13    MOVR0、R3
 14    加算 SP、FP#0 
15    ポップ {FP} (LDRのFP、[SP]、#4)
16    のBX LR

コンパイルされたコードの部分列6-11前記アレイ1に割り当てられたプログラムの最初のバイト、残りのバイトはゼロに割り当てられていることを除いて、明確。

 

第二に、グローバル変数の初期化セクション

我々は、初期化されるグローバル変数を作成する方法については、以下のあなたが0の変数の初期値を作成する場合は、その後、「= 0」の割り当てはそれを省略することができます言いましたか?

料金はすべてを説明するためのコードを使用して、あまり話をしませんでした。

次のシナリオは、プロジェクトの実現のために、同社は、module_a.cプログラマはプログラムを書く場合は、彼の同僚は次のように最後の二人は、ソースコードを書くために、module_b.cのBプログラムを書きました:

1  / * module_a.c * / 
2の#include <stdio.hの>
 3  
4  ボイド関数(ボイド)。
5  
6  INT  グローバル = 0 7  
8  のint main()の
 9  {
 10      グローバル = 3 11      関数();
12      のprintf(" メイン:%Dを\ n "グローバル)。
13      リターン 0 14 }
1  / * module_b.c * / 
2の#include <stdio.hの>
 3  
4  INT  グローバル5  
6  ボイド関数(ボイド7  {
 8      グローバル = 6 9      のprintf(" 機能:%Dを\ n "グローバル)。
10      リターン 0 ;
11 }

二人はグローバルと同じグローバル変数の協和定義を持っていますが、見落としBは、初期化しグローバルに忘れてしまいました。

通常でコンパイルされ、結果は以下の通りであります:

機能:6 
メイン:6

私たちは、私の同僚、不可解な業績を生み出したモジュールのコンパイルを見ることができます。なぜ、同じ名前のグローバル変数を定義し、コンパイラがそれを訴えないのですか? 私たちは、探求し続けます。

まず、ソースファイルがオブジェクトファイルにコンパイルされ、その後、readelfがの内容を表示するためにツールを使用します。

腕のlinux-gccの- C module_x.c  -linux-readelfが-a module_x.o

唯一のこれの関連する内容の除去  、次のようにグローバル識別子モジュールは、次のとおりです。

    ... 
[ 4 ] .bssのNOBITS     00000000  000078  000004  00 WA 0  0  4 
    ... 
1300000000     4 OBJECTグローバルなデフォルト     4     グローバル
    ...

次のようにBグローバル識別モジュールです。

    ...
 1200000004     4 OBJECTグローバルなデフォルトCOM グローバル
    ...

それは、グローバル変数が0に初期化されるセクションを.bssにするために組み合わさ、COM(共通ブロック)セグメントに組み込まれ、初期化されていないグローバル変数。その理由は、GCCコンパイラや従来のUNIX Cコンパイラ、共通ブロックに配置された初期化されていないグローバル変数のデフォルトの動作と一致して、  共通ブロックは弱いシンボル(weakシンボル)に相当し、そのリンクは文句を言わないとき、これはバグを特定するのは非常に難しいかもしれません。

 

Web上で見つかった以下の要約:

  同じ名前とシンボリックリンクの弱いグローバルシンボルは間違って行くことができない、リンカはグローバルシンボルを選択します。グローバルシンボルおよび共通ブロック内の同じ名前の数である場合、同様に、リンカーは、グローバル・シンボルを選択します。つまり、リンクが初期化されていないグローバル変数が弱いシンボルであると考えられています。

もちろん、この出来事を回避する方法があり、私たちは、同じ名前のグローバル変数が存在する場合、コンパイル時にこの機能のgccをオフに-fno-共通の属性を追加することができ、それはエラーのリンク、ユーザーの意識を生成します。問題。

おすすめ

転載: www.cnblogs.com/GyForever1004/p/11448828.html