2013-12-04 3 views
3

Мне интересно, почему этот код компилируется и запускается. Я думал, что если переменная объявлена ​​как статическая (в глобальной области), она будет доступна только в объявленном файле.Объявление extern и глобальный масштаб

functions.h

static int x = 10; 

main.c

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

extern int x; 

int main() 
{ 
    printf("%d", x); 
} 
+0

Это может помочь http://stackoverflow.com/questions/5040525/static-variable-in-a-header-file – Arya

+0

Я бы не назвал это лучшая практика, чтобы объявить 'static' переменные в заголовке. –

+0

@ Klas Lindbäck тогда где? – DRON

ответ

0

Препроцессор принимает текст в functions.h и копирует его как в main.c После предварительной обработки (и до компиляции) ваш main.c выглядит следующим образом:

#include <stdio.h> 
static int x = 10; 

extern int x; 

int main() 
{ 
    printf("%d", x); 
} 

Вы будете иметь проблемы компоновщика если функции.h включены во второй исходный файл, и вы пытаетесь связать оба объектных файла в один исполняемый файл.

+0

Проблемы с компоновщиками? 'functions.h' может быть включен в любое количество файлов без проблемы с компоновщиком, поскольку имена переменных' static' не отображаются в компоновщике. –

+0

Коррекция: для gcc: В C++ существует ошибка компоновщика (несколько определений x), если int x; определяется в двух разных исходных файлах, и оба объектных файла связаны друг с другом (в C это просто отлично); если статический int x; в обоих исходных файлах, то это не ошибка компоновщика. – MichaelMoser

+0

'extern' и' static' противоречивы, поэтому объединение их - плохая идея. –

1

Технически это действительно объявлена ​​в main.c, так как это включает в себя functions.h. Если бы это был разрозненный модуль компиляции, вы были бы правы.

Но я бы предположил, что в том же компиляционном блоке extern и static столкнутся друг с другом. По крайней мере, стоит предупредить.

+1

Объявление с 'extern' после объявления с' static', которое в области принимает 'static', за C 2011 (N1570) 6.2.3 4:« Для идентификатора, объявленного с классом хранения спецификатор extern в области, в которой видимо предварительное объявление этого идентификатора, если предыдущее объявление указывает внутреннюю или внешнюю привязку, ссылка идентификатора в более позднем объявлении такая же, как ссылка, указанная в предыдущем объявлении. » –

+0

@ EricPostpischil Это было ново для меня, спасибо. Есть ли какие-нибудь полезные для этого способы? – glglgl

-1

, когда вы включаете functions.h в main.c, вы на самом деле скопировать содержание function.h в main.c так что ваш окончательный код стать чем-то вроде:

#include <stdio.h> 
static int x = 10; 

extern int x; 

int main() 
{ 
    printf("%d", x); 
} 

Так что ваша ехЬегп линия является излишним. вы можете добиться того, что вы хотите этим удалить #include "functions.h" из main.c

  1. компиляции function.h с помощью g++ -c function.h
  2. компиляции main.c, используя g++ -c main.c
  3. затем построить g++ function.o main.o -o out третьей линии не будет компилировать, потому что от static int.
Смежные вопросы