10

私は夢中になっていると確信していますが、次の C コードを考えてみてください。

// file1.c
int first;

void f(void)
{ first = 2; }

// file2.c
#include <stdio.h>

int first;
void f();
int main(void)
{
    first = 1;
    f();
    printf("%d", first);
}

これらの 2 つのファイルは、何らかの理由でコンパイルおよびリンクされ、2. firstwithのどちらか一方 (両方ではない) の定義にラベルを付けない限りextern、これはコンパイルされず、実際にはextern!の要点であるという印象を受けていました。

4

2 に答える 2

10

は 2 回しか宣言されていないため、コンパイルされるfirstだけです。メモリには実際には 2 つの場所ではなく、1 つの場所しかありません。最初に 1 つを初期化し、もう 1 つを で初期化すると、リンカにエラーが表示されます。たとえば、GCC:int first=4;int first=5;

b.o:b.c:(.data+0x0): multiple definition of `_first'
a.o:a.c:(.data+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
于 2013-02-22T14:14:58.110 に答える
7

通常の状態 (追加の gcc フラグなし) では、このコードを次のようにコンパイルしても問題ありません。

gcc file1.c file2.c

コンパイラは、同じ名前の 2 つのグローバル変数があり、どちらも初期化されていないことを認識します。次に、初期化されていないグローバル変数をコードの「共通」セクションに配置します**。つまり、「最初の」変数のコピーは 1 つだけになります。これは、のデフォルトgcc-fcommon

フラグを付けてコンパイルすると、-fno-common考えていたエラーが表示されます。

/tmp/ccZNeN8c.o:(.bss+0x0): multiple definition of `first'
/tmp/cc09s2r7.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

これを解決するexternには、1 つを除くすべての変数に追加します。

警告:
ここで、サイズが異なる 2 つのグローバルな初期化されていない配列があるとします。

// file1.c
int first[10];

// file2.c
int first[20];

それらをコンパイルしても警告やエラーgcc -Wall file1.c file2.cは発生せず、サイズが異なっていても変数は共通にされました!!!

 //objdump from file1.c:
 0000000000000028       O *COM* 0000000000000020 first

 //objdump from file2.c:
 0000000000000050       O *COM* 0000000000000020 first

これは、グローバル変数の危険性の 1 つです。


**objdump *.o ファイル (gcc -cそれらを生成するにはコンパイルする必要があります) を見るとfirst、共通 ( *COM*) セクションに配置されていることがわかります。

mike@mike-VirtualBox:~/C$ objdump -t file2.o

a.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 file2.c
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata    0000000000000000 .rodata
0000000000000000 l    d  .note.GNU-stack    0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame
0000000000000000 l    d  .comment   0000000000000000 .comment
0000000000000004       O *COM*  0000000000000004 first
0000000000000000 g     F .text  0000000000000039 main
0000000000000000         *UND*  0000000000000000 f
0000000000000000         *UND*  0000000000000000 printf
于 2013-02-22T14:23:44.683 に答える