Как использовать extern для обмена переменными между исходными файлами? - PullRequest
907 голосов
/ 16 сентября 2009

Я знаю, что глобальные переменные в C иногда имеют ключевое слово extern. Что такое переменная extern? Как выглядит декларация? Каков его объем?

Это связано с совместным использованием переменных в исходных файлах, но как это работает точно? Где я могу использовать extern?

Ответы [ 17 ]

5 голосов
/ 09 января 2019
                 declare | define   | initialize |
                ----------------------------------

extern int a;    yes          no           no
-------------
int a = 2019;    yes          yes          yes
-------------
int a;           yes          yes          no
-------------

Объявление не будет выделять память (переменная должна быть определена для выделения памяти), но определение будет. Это просто еще один простой взгляд на ключевое слово extern, поскольку другие ответы действительно хороши.

5 голосов
/ 03 октября 2012

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

Если вы не хотите, чтобы программа обращалась к вашим переменным или функциям, вы используете static, который сообщает компилятору, что эту переменную или функцию нельзя использовать вне этого модуля.

5 голосов
/ 27 января 2016

extern просто означает, что переменная определена в другом месте (например, в другом файле).

4 голосов
/ 09 августа 2012

Во-первых, ключевое слово extern не используется для определения переменной; скорее это используется для объявления переменной. Я могу сказать, extern - это класс хранения, а не тип данных.

extern используется, чтобы другие C-файлы или внешние компоненты знали, что эта переменная уже где-то определена. Пример: если вы создаете библиотеку, нет необходимости обязательно определять глобальную переменную где-то в самой библиотеке. Библиотека будет скомпилирована напрямую, но при связывании файла она проверяет определение.

3 голосов
/ 01 сентября 2014

extern используется, поэтому один файл first.c может иметь полный доступ к глобальному параметру в другом файле second.c.

extern может быть объявлено в файле first.c или в любом из заголовочных файлов, которые first.c включает.

2 голосов
/ 09 октября 2018

С xc8 вы должны быть осторожны при объявлении переменной как тот же тип в каждом файле, как вы могли, по ошибке, объявить что-то int в одном файле и char сказать в другом. Это может привести к повреждению переменных.

Эта проблема была элегантно решена на форуме по микрочипам около 15 лет назад. / * См. «Http: www.htsoft.com» / /"forum / all / showflat.php / Cat / 0 / Number / 18766 / an / 0 / page / 0 # 18766"

Но эта ссылка, похоже, больше не работает ...

Итак, я быстро попытаюсь объяснить это; сделать файл с именем global.h.

В нем заявляют следующее

#ifdef MAIN_C
#define GLOBAL
 /* #warning COMPILING MAIN.C */
#else
#define GLOBAL extern
#endif
GLOBAL unsigned char testing_mode; // example var used in several C files

Теперь в файле main.c

#define MAIN_C 1
#include "global.h"
#undef MAIN_C

Это означает, что в main.c переменная будет объявлена ​​как unsigned char.

Теперь в других файлах просто включается global.h объявить его как extern для этого файла .

extern unsigned char testing_mode;

Но он будет правильно объявлен как unsigned char.

Старый пост на форуме, вероятно, объяснил это немного яснее. Но это реальный потенциал gotcha при использовании компилятора это позволяет вам объявить переменную в одном файле, а затем объявить ее extern как другой тип в другом файле. Проблемы, связанные с то есть если вы говорите, объявил testing_mode как int в другом файле он бы подумал, что это 16-битная переменная и перезапишет какую-то другую часть памяти, что может привести к повреждению другой переменной. Сложно отлаживать!

0 голосов
/ 24 июня 2019

Очень короткое решение, которое я использую, чтобы позволить заголовочному файлу содержать внешнюю ссылку или фактическую реализацию объекта. Файл, который на самом деле содержит объект, просто делает #define GLOBAL_FOO_IMPLEMENTATION. Затем, когда я добавляю новый объект в этот файл, он также появляется в этом файле, и мне не нужно копировать и вставлять определение.

Я использую этот шаблон для нескольких файлов. Поэтому для того, чтобы все было как можно более автономно, я просто повторно использую один макрос GLOBAL в каждом заголовке. Мой заголовок выглядит так:

//file foo_globals.h
#pragma once  
#include "foo.h"  //contains definition of foo

#ifdef GLOBAL  
#undef GLOBAL  
#endif  

#ifdef GLOBAL_FOO_IMPLEMENTATION  
#define GLOBAL  
#else  
#define GLOBAL extern  
#endif  

GLOBAL Foo foo1;  
GLOBAL Foo foo2;


//file main.cpp
#define GLOBAL_FOO_IMPLEMENTATION
#include "foo_globals.h"

//file uses_extern_foo.cpp
#include "foo_globals.h
...