c/c++のグローバル変数

4009 ワード

https://www.byvoid.com/blog/c-global-variables-in-multiple-files
まずコードを見てみましょう
func.c
int buf = 0;

void func() {
  buf = 2;
  /* Do something else */
}

main.c
#include <stdio.h>

int buf;
void func();

int main() {
  buf = 1;
  func();
  printf("%d
"
, buf); return 0; }

2つのファイルをコンパイルして、出力した結果はどうなりますか?一目で見ると、2つのグローバル変数bufが異なるファイルにあり、extern宣言もないため、1が出力される可能性があります.明らかに2つですか.しかし、実際にはその実行結果は2であり、この2つのファイルで参照されているのは変数であることを示しています.
これはなぜですか.なぜなら、コンパイル時に、C言語コンパイラはグローバルシンボルをstrongとweakの2種類としてマークします.
  • 関数および初期化されたグローバルシンボルはstrong
  • としてマークされる.
  • 初期化されていないグローバルシンボルはweak
  • としてマークする.
    接続時、コネクタによる多重定義のグローバルシンボルの解析の原則は次のとおりです.
  • 同じ記号では、複数のstrong定義は許可されません.
  • 1シンボルに1つのstrong定義と複数のweak定義がある場合、シンボルのstrong定義が採用される.
  • 1 1つのシンボルに複数のweak定義がある場合、任意のweak定義
  • を選択する.
    2つの変数は1つが初期化され、1つは初期化されていないため、1つはstrongで、1つはweakなので、コネクタはシンボル解析時に彼らを1つと見なします.
    もし私たちがmainをcのbufも初期化されました.
    #include <stdio.h>
    
    int buf = 0;
    void func();
    
    int main() {
      buf = 1;
      func();
      printf("%d
    "
    , buf); return 0; }

    再コンパイルすると
    duplicate symbol _buf in:
        /var/folders/44/_cc501qx1jd1p5bfrjbk6b100000gn/T//ccZ87C6g.o
        /var/folders/44/_cc501qx1jd1p5bfrjbk6b100000gn/T//ccZlES8n.o
    ld: 1 duplicate symbol for architecture x86_64
    collect2: ld returned 1 exit status

    これは、両方のグローバル変数がstrongであるためです.Makefile:
    tst:main.o func.o gcc -o tst main.o func.o main.o:main.c func.o:func.c clean: rm *.o tst
    ファイル内の位置合わせは4つのスペースではなくtapです.
    まず2つを合わせます.cファイルコンパイル生成.oファイル、また.oファイルを実行可能ファイルにリンクする
    g++-o tst mainをそのまま使うと.c func.cコンパイルエラー
    はい.hまたは.cppで定義するグローバル変数またはグローバル関数は、理論的にはすべてのファイルが直接呼び出すことができるが、注意しなければならないのは避けたほうがいい.hにグローバル変数またはグローバル関数を定義し、複数のファイルがあるとincludeという.hファイルでは、複数回定義されたエラーが発生します
    適切な方法は次のとおりです.
    グローバル変数については.hでexternで宣言し、.cで定義
    グローバル関数については.h声明、在.c定義
    直接でもいいです.cではグローバル変数を定義しますが、他のファイルは直接呼び出すことはできません.
    http://blog.csdn.net/sunmenggmail/article/details/7568418