Как правильно использовать ключевое слово extern в C



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



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



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



Edit: если вы extern что-то, когда это объявление по умолчанию без ключевого слова в заголовочном файле?

539   10  
c

10 ответов:

"extern" изменение связей. С помощью ключевого слова предполагается, что функция / переменная доступна где-то еще, и разрешение откладывается на компоновщик.

есть разница между" extern " на функциях и на переменных: на переменных он не создает экземпляр самой переменной, т. е. не выделяет никакой памяти. Это нужно сделать где-то еще. Таким образом, это важно, если вы хотите импортировать переменную из другого. Для функций, это только говорит компилятор эта связь является внешней. Поскольку это значение по умолчанию (вы используете ключевое слово "static", чтобы указать, что функция не связана с помощью extern linkage), вам не нужно использовать его явно.

extern сообщает компилятору, что эти данные определяются где-то и будут связаны с линкером.

С помощью ответов здесь и говорить с несколькими друзьями вот практический пример использования extern.

Пример 1. чтобы показать ловушку:

File stdio.h:

int errno;
/* other stuff...*/

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

если myCFile1.o и myCFile2.o связаны, каждый из файлов c имеет отдельные копии errno. Это проблема, так как одно и то же errno должен быть доступен во всех связанных файлах.

Пример 2. исправление.

File stdio.h:

extern int errno;
/* other stuff...*/

File stdio.c

int errno;

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

теперь, если оба myCFile1.o и MyCFile2.o связаны компоновщиком, они оба будут указывать на одно и то же errno. Таким образом, решая реализацию с extern.

уже было заявлено, что extern ключевое слово является избыточным для функции.

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

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

(Если требуется статическая связь, функция должна быть объявлена как "статическая" как в ее прототипе, так и в заголовке функции, и они обычно должны быть одинаковыми .файл c).

много лет спустя я открываю для себя этот вопрос. Прочитав все ответы и комментарии, я, хотя и мог бы уточнить несколько деталей ... Это может быть полезно для людей, которые попадают сюда через goggle search.

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

давайте определим 3 прототипа функций

//--------------------------------------
//Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
       int function_3(void);

файл заголовка может использоваться основным исходным кодом в качестве следуйте

//--------------------------------------
//Filename: "my_project.C"
#include "my_project.H"

void main(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 1234;

чтобы скомпилировать и связать, мы должны определить "function_2" в том же файле исходного кода, где мы вызываем эту функцию. Две другие функции могут быть определены в другом исходном коде".C " или они могут быть расположены в любом двоичном файле (.ПАРАМЕТР OBJ.* ,БИБЛИОТЕКА.* ,DLL), для которого у нас может не быть исходного кода.

давайте снова включим заголовок " my_project.H" в другом "*.C " файл, чтобы лучше понять разницу. В этом же проекте мы добавьте следующий файл //--------------------------------------

//Filename: "my_big_project_splitted.C"
#include "my_project.H"

void old_main_test(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 5678;

int function_1(void) return 12;
int function_3(void) return 34;

важные особенности, чтобы заметить: Когда функция определена как "статическая" в заголовочном файле, компилятор / компоновщик должен найти экземпляр функции с этим именем в каждом модуле, который использует этот файл include.

функция, которая является частью библиотеки C, может быть заменена только в одном модуле путем переопределения прототипа с помощью "статического" только в этом модуле. Например, замените любой вызов на "malloc" и "бесплатно", чтобы добавить функцию обнаружения утечки памяти.

спецификатор "extern" на самом деле не нужен для функций. Когда " статический "не найден, функция всегда считается "extern".

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

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

очень хорошая статья, что я пришел о extern ключевое слово, вместе с примерами:http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

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

Если каждый файл в вашей программе сначала компилируется в объектный файл, то объектные файлы связаны между собой, вам нужно extern. Он говорит компилятору: "эта функция существует, но код для нее находится где-то в другом месте. Не паникуй."

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

исключения из этого правила-это встроенные функции, определенные в заголовке, и переменные, которые, хотя и определены в заголовке , должны быть локальными для единицы перевода (исходный файл, в который включается заголовок): они должны быть static.

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

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


объявление прототипов функций extern на самом деле не нужно. Некоторые люди не любят его, потому что он будет просто тратить пространство и объявления функций уже имеют тенденцию к переполнению линии пределы. Другим это нравится, потому что таким образом, функции и переменные можно рассматривать одинаково.

когда у вас есть эта функция, определенная на другой dll или lib, так что компилятор переходит к компоновщику, чтобы найти его. Типичный случай, когда вы вызываете функции из API ОС.

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

большую часть времени ваши функции будут одной из следующих (больше похоже на лучшую практику):

  • статические (нормальные функции, которые не являются виден снаружи .c file)
  • static inline (inlines from .c или .ч файлы)
  • extern (объявление в заголовках следующий вид (см. ниже))
  • [нет слов] (нормальный функции, предназначенные для доступа с помощью Экстерн деклараций)

Comments

    Ничего не найдено.