Разница между объявлением переменной с внешним и без него - PullRequest
0 голосов
/ 21 января 2020

1.h

extern int a;

1.c

#include <stdio.h>
#include "1.h"

int main(){ 
 printf("%d\n", a);
 return 0;
}

2.c

#include "1.h"

int a = 6;

Это компилируется и работает очень хорошо (g cc 1. c 2. c) при удалении extern из 1.h и печати 6. Я знаю, что удаление может привести к определению a в каждой единице перевода (объектном файле), но в чем проблема? не компоновщик просто git избавиться от него при компоновке, так как он компилируется без ошибок?

1 Ответ

2 голосов
/ 21 января 2020

Этот метод не соответствует букве стандарта C и «правила одного определения» - это официально неопределенное поведение:

J.2 Не определено поведение

Идентификатор с внешней связью используется, но в программе не существует точно одного внешнего определения для идентификатора, или идентификатор не используется, и существует несколько внешних определений для идентификатор (6.9).

§6.9 Внешние определения ¶5

внешнее определение является внешней декларацией, которая также является определением функции (кроме встроенного определения) или объекта. Если идентификатор, объявленный с внешней связью, используется в выражении (кроме как в качестве части операнда оператора sizeof или _Alignof, результатом которого является целочисленная константа), где-то во всей программе должно быть ровно одно внешнее определение для идентификатора; в противном случае должно быть не более одного. 161)

161) Таким образом, если идентификатор, объявленный с внешней связью, не используется в выражении, необходимо быть внешним определением для него.

подробнее здесь: Как использовать extern для обмена переменными между исходными файлами?

...