Что такое внешняя связь и внутренняя связь? - PullRequest
306 голосов
/ 31 августа 2009

Я хочу понять внешнюю связь и внутреннюю связь и их различие.

Я также хочу знать значение

const переменные внутренне связаны по умолчанию, если иное не объявлено как extern.

Ответы [ 9 ]

269 голосов
/ 31 августа 2009

Как сказал dudewat внешняя связь означает, что символ (функция или глобальная переменная) доступна в вашей программе, а внутренняя связь означает, что она доступна только в переводчик .

Вы можете явно контролировать связь символа, используя ключевые слова extern и static. Если связь не указана, то по умолчанию используется extern для не const символов и static (внутренняя) для const символов.

// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static

// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static 

Обратите внимание, что вместо использования static для внутренней связи лучше использовать анонимные пространства имен , в которые вы также можете поместить class es. Связь между анонимными пространствами имен изменилась между C ++ 98 и C ++ 11, но главное, что они недоступны из других модулей перевода.

namespace {
   int i; // external linkage but unreachable from other translation units.
   class invisible_to_others { };
}
244 голосов
/ 31 августа 2009

Когда вы пишете файл реализации (.cpp, .cxx и т. Д.), Ваш компилятор генерирует единицу перевода . Это объектный файл из вашего файла реализации плюс все заголовки, которые вы #include d в нем.

Внутренняя связь относится ко всему только в объеме единицы перевода .

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

86 голосов
/ 26 февраля 2010
  • Глобальная переменная имеет внешнюю связь по умолчанию. Его область действия может быть расширена на файлы, отличные от содержащих его, с помощью соответствующего объявления extern в другом файле.
  • Область действия глобальной переменной может быть ограничена файлом, содержащим ее объявление, путем добавления префикса объявления к ключевому слову static . Говорят, что такие переменные имеют внутреннюю связь .

Рассмотрим следующий пример:

1.cpp

void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
    int a;
    //...
    f(a);
    //...
    f(a);
    //...
}
  1. Сигнатура функции f объявляет f как функцию с внешней связью (по умолчанию). Его определение должно быть предоставлено позже в этом файле или в другой единице перевода (приведено ниже).
  2. max определяется как целочисленная константа. Связывание по умолчанию для констант: internal . Его связь меняется на внешнюю с ключевым словом extern . Так что теперь максимум можно получить в других файлах.
  3. n определяется как целочисленная переменная. Связывание по умолчанию для переменных, определенных вне тел функций: external .

1036 * файле 2.cpp * #include <iostream> using namespace std; extern const int max; extern int n; static float z = 0.0; void f(int i) { static int nCall = 0; int a; //... nCall++; n++; //... a = max * z; //... cout << "f() called " << nCall << " times." << endl; } max имеет внешнюю связь 1041 *. Соответствующее определение для max (с внешней связью) должно появиться в некотором файле. (Как в 1.cpp) n имеет внешнюю связь . z определено как глобальная переменная с внутренней связью . Определение nCall определяет, что nCall является переменной, которая сохраняет свое значение при вызовах функции f (). В отличие от локальных переменных с классом автоматического хранения по умолчанию, nCall будет инициализироваться только один раз в начале программы, а не один раз для каждого вызова функции f (). Спецификатор класса хранения static влияет на время жизни локальной переменной, а не на ее область действия. Примечание: Ключевое слово static играет двойную роль. При использовании в определениях глобальных переменных он определяет внутреннюю связь . При использовании в определениях локальных переменных он указывает, что время жизни переменной будет продолжительностью программы, а не продолжительностью функции. Надеюсь, это поможет!

25 голосов
/ 12 августа 2010

В терминах «C» (поскольку ключевое слово static имеет различное значение между «C» и «C ++»)

Давайте поговорим о другой области видимости в 'C'

ОБЛАСТЬ ПРИМЕНЕНИЯ: Это в основном, как долго я могу что-то увидеть и как далеко.

  1. Локальная переменная: область видимости только внутри функции. Он находится в области памяти STACK. Это означает, что каждый раз, когда функция вызывается все переменные которые являются частью этой функции, в том числе аргументы функции только что созданные и уничтоженные, когда контроль выходит из функция. (Поскольку стек очищается каждый раз, когда функция возвращает)

  2. Статическая переменная: это область действия для файла. Он доступен везде, где в файле
    в котором это заявлено. Он находится в сегменте памяти DATA. поскольку это может быть доступно только внутри файла и, следовательно, ВНУТРЕННЕЙ связи. Любой
    другие файлы не могут видеть эту переменную. На самом деле ключевое слово STATIC является Единственный способ, которым мы можем ввести некоторый уровень данных или функции
    прячется в 'C'

  3. Глобальная переменная: область применения для всего приложения. Это доступно из каждого где из приложения. Глобальные переменные также находятся в сегменте DATA Поскольку к нему можно получить доступ в любом месте приложения и, следовательно, ВНЕШНЯЯ СВЯЗЬ

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

10 голосов
/ 06 сентября 2016

Прежде чем говорить о вопросе, лучше узнать термин единица перевода , , программа и некоторые базовый Понятия C ++ (на самом деле связывание является одним из них в общем) точно. Вы также должны будете знать, что такое scope .

Я выделю некоторые ключевые моменты, особенно пропавших без вести в предыдущих ответах.

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

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

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

(Упс ... Я обнаружил, что набрал несколько повторений стандартную формулировку ...)

Есть также некоторые другие запутанные моменты, которые не охватываются языковой спецификацией.

  1. Видимость (имени). Это также свойство объявленного имени, но со значением, отличным от связи .
  2. Видимость (побочного эффекта) . Это не относится к этой теме.
  3. Видимость (символа). Это понятие может использоваться в реальных реализациях . В таких реализациях символ с определенной видимостью в объектном (двоичном) коде обычно является целью, отображаемой из определения сущности, чьи имена имеют такую ​​же конкретную связь в исходном (C ++) коде. Тем не менее, это обычно не гарантируется один на один. Например, символ в образе динамической библиотеки может быть указан только для внутреннего использования в этом изображении из исходного кода (связан с некоторыми расширениями, как правило, __attribute__ или __declspec) или параметров компилятора, и изображение не является всей программой или объектный файл, переведенный из модуля перевода, поэтому ни одна стандартная концепция не может точно его описать. Поскольку символ не является нормативным термином в C ++, это всего лишь подробности реализации, даже несмотря на то, что соответствующие расширения диалектов могли быть широко приняты.
  4. Доступность. В C ++ это обычно свойство членов класса или базовых классов , что опять-таки является другим понятием, не связанным с темой.
  5. Global. В C ++ «глобальный» относится к глобальному пространству имен или глобальной области имен. Последнее примерно эквивалентно области файлов на языке Си. Как в C, так и в C ++, связь не имеет ничего общего с областью действия, хотя область (например, связь) также тесно связана с идентификатором (в C) или именем (в C ++), введенным некоторым объявлением.

Правило связывания области имен const переменная является чем-то особенным (и особенно отличается от объекта const, объявленного в области файлов на языке C, который также имеет концепцию связывания идентификаторов). Поскольку ODR обеспечивается C ++, важно сохранить не более одного определения одной и той же переменной или функции, встречающейся во всей программе, за исключением inline functions . Если такого специального правила для const нет, то самое простое объявление переменной const с инициализаторами (например, = xxx) в заголовке или в исходном файле (часто это «файл заголовка»), включаемое несколькими единицами перевода (или включение одной единицы перевода более одного раза (хотя и редко) в программу нарушит ODR, что делает невозможным использование переменной const, поскольку замена некоторых объектоподобных макросов невозможна.

5 голосов
/ 23 февраля 2017

Я думаю Внутренняя и внешняя связь в C ++ дает ясное и краткое объяснение:

Единица перевода относится к файлу реализации (.c / .cpp) и всем файлы заголовков (.h / .hpp), которые он включает. Если объект или функция внутри такая единица перевода имеет внутреннюю связь, то эта конкретная Символ виден только компоновщику внутри этого блока перевода. Если объект или функция имеет внешнюю связь, компоновщик также может видеть ее при обработке других переводческих единиц. Ключевое слово static при использовании в глобальном пространстве имен заставляет символ иметь внутреннюю связь. Ключевое слово extern приводит к тому, что символ имеет внешнюю связь.

Компилятор по умолчанию связывает символы так:

Неконстантные глобальные переменные по умолчанию имеют внешнюю связь
Глобальные переменные Const по умолчанию имеют внутреннюю связь
Функции имеют внешнюю связь по умолчанию

4 голосов
/ 17 ноября 2017

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

  1. Внутренняя связь : идентификаторы можно увидеть только внутри единицы перевода.
  2. Внешняя связь : идентификаторы можно увидеть (и сослаться) в других единицах перевода.
  3. Нет связи : идентификаторы можно увидеть только в той области, в которой они определены. Связь не влияет на область видимости

только C ++ : Вы также можете иметь связь между фрагментами кода C ++ и не-C ++, которая называется языковая связь .

Источник: IBM Program Linkage

4 голосов
/ 12 октября 2017

* В основном 1002 *

  • extern linkage переменная видна во всех файлах
  • internal linkage переменная видна в одном файле.

Объясните: переменные const внутренне связаны по умолчанию, если не указано иное как extern

  1. по умолчанию, глобальная переменная external linkage
  2. но, const глобальная переменная internal linkage
  3. дополнительно, extern const глобальная переменная external linkage

Довольно хороший материал о связях в C ++

http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/

0 голосов
/ 08 августа 2018

В С ++

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

Глобальные переменные и обычные функции имеют внешнюю связь.

Статическое имя объекта или функции в области видимости файла является локальным для единицы перевода. То есть называется Внутренняя связь

Связывание относится только к элементам, которые имеют адреса во время ссылки / загрузки; таким образом, объявления классов и локальные переменные не имеют связи.

...