4

ヘッダー ファイルでの extern およびグローバル変数宣言の使用法を理解しようとしているので、C で記述された次のテスト プログラムを思いつきました。

main.c ファイル

//main.c
#include "global.h"
#include <stdio.h>

int nExternValue = 6;

int main(int argc, char* argv[])
{
    printf("%d \n", nValue);
    printf("%d \n", nExternValue);

    AddToValue();

    printf("%d \n", nValue);
    printf("%d \n", nExternValue);
}

global.h ファイル

#ifndef _GLOBAL_H
#define _GLOBAL_H

//WRONG! do not declare a variable here
int nValue;

//OK! extern variable makes it a global accessable variable
extern int nExternValue;

//OK! function prototype can be placed in h file
int AddToValue();

#endif

AddToValue 関数を実装する AddValue.c ファイル。

#include "global.h"

int AddToValue() {
    nValue++;
    nExternValue++;
}

gcc を使用してアプリをコンパイルし、実行しました。

$ gcc main.c AddValue.c -o test
$./test
0 
6 
1 
7 

g++ を使用してアプリをコンパイルしたところ、次のリンカ エラーが発生しました。

$ g++ main.c AddValue.c -o test
/tmp/ccFyGDYM.o:(.bss+0x0): multiple definition of `nValue'
/tmp/cc3ixXdu.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

gcc リンカがエラーを生成しないのはなぜですか? nValue 変数が複数回宣言されると、エラーが発生します。

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4

2 に答える 2

4

gcc でコンパイルすると、初期化されていないグローバル変数 (nValue など) は共通シンボルとして扱われます。異なるコンパイル単位で発生した同じ共通シンボルは、リンク時にマージされます。g++ でコンパイルされた場合 (ソース プログラムが C++ プログラムとして扱われることを意味します)、初期化されていないグローバル変数はデフォルト値 0 で暗黙的に初期化されます。 global.h は複数のソース ファイルに含まれているため、コンパイラはシンボル nValue が定義されていると見なします。複数回。

この投稿もご覧ください: Why uninitialized global variable is weak symbol?

于 2012-11-28T02:23:28.517 に答える
4

C と C++ は異なる言語です。適切な例として、上記のプログラムは有効な C プログラムですが、不適切な形式の C++ プログラムです。C++ の 1 つの定義規則に違反しています。C には対応する規則はありません。

gcc でコンパイルすると、上記のテキストが C プログラムとしてコンパイルされます。g++ でコンパイルすると、上記のテキストが C++ プログラムとしてコンパイルされます。

于 2012-11-28T02:18:23.533 に答える