Відповіді:
При записі файлу реалізації ( .cpp
, .cxx
і т.д.) , компілятор генерує одиницю перекладу . Це вихідний файл вашої реалізації, а також усі заголовки, які ви будете мати #include
в ньому.
Внутрішня зв'язок стосується всього лише сфери перекладу .
Зовнішня посилання стосується речей, які існують поза певною одиницею перекладу. Іншими словами, доступний через всю програму , яка є комбінацією всіх перекладацьких одиниць (або об’єктних файлів).
const
змінних (як і його призначення) тут повністю пропущено.
Як зазначає 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 { };
}
extern
оголошення в іншому файлі.static
. Кажуть, що такі змінні мають внутрішній зв'язок .Розглянемо наступний приклад:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
оголошується f
функцією із зовнішнім зв’язком (за замовчуванням). Його визначення повинно бути надано пізніше у цьому файлі чи в іншому підрозділі перекладу (подано нижче).max
визначається як ціла константа. За замовчуванням зв'язок для констант є внутрішньою . Його зв'язок змінюється на зовнішню за допомогою ключового слова extern
. Тож тепер max
можна отримати доступ до інших файлів.n
визначається як ціла змінна. Зв'язок за замовчуванням для змінних, визначених поза тілами функцій, є зовнішнім .#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
оголошено, що має зовнішню зв'язок . У max
деякому файлі повинно з’явитися відповідне визначення для (із зовнішньою зв'язком). (Як у 1.cpp)n
оголошено, що має зовнішню зв'язок .z
буде визначена як глобальна змінна з внутрішнім зв'язком .nCall
вказує nCall
на змінну, яка зберігає своє значення для викликів до функції f()
. На відміну від локальних змінних з класом автоматичного зберігання за замовчуванням, nCall
буде ініціалізовано лише один раз на початку програми, а не один раз для кожного виклику f()
. Специфікатор класу зберігання static
впливає на термін служби локальної змінної, а не на її обсяг.Примітка: ключове слово static
відіграє подвійну роль. При використанні у визначеннях глобальних змінних він визначає внутрішню взаємозв'язок . При використанні у визначеннях локальних змінних він вказує, що тривалість роботи змінної буде тривалістю програми, а не тривалістю функції.
Сподіваюся, що це допомагає!
static
дозволяє ледача одиночна ініціалізація (яка може бути корисною, якщо вам потрібен глобальний ish об'єкт, але повинна контролювати, коли вона побудована через проблеми із глобальним порядком побудови та не може динамічно розподілити її використання в new
той час як більш поглиблені схеми ініціалізації можуть бути вищими за рамки необхідних для відповідного об'єкта; за наслідком це, головним чином, проблема вбудованих систем, які використовують C ++).
Давайте поговоримо про різну сферу застосування у "C"
ОБЛАСТЬ: В основному, як довго я щось бачу і як далеко.
Локальна змінна: Область застосування лише всередині функції. Він знаходиться в області STACK в оперативній пам'яті. Що означає, що кожного разу, коли функція отримує виклик, всі змінні, що входять до складу цієї функції, включаючи аргументи функції, щойно створюються та знищуються, коли контроль виходить із функції. (Оскільки стек розмивається щоразу, коли функція повертається)
Статична змінна: Обсяг цього стосується файлу. Він доступний скрізь у файлі,
в якому він оголошений. Він знаходиться в сегменті оперативної пам'яті DATA. Оскільки це можна отримати лише у файлі, а значить, і ВНУТРІШНЕ посилання. Будь-які
інші файли не можуть бачити цю змінну. Насправді ключове слово STATIC - це єдиний спосіб, коли ми можемо ввести певний рівень даних або функцій, що
ховаються у "C"
Глобальна змінна: Обсяг цього стосується цілої програми. Це доступна форма у будь-якому місці програми. Глобальні змінні також розміщені в сегменті DATA, оскільки до нього можна отримати доступ будь-де в додатку, а значить і ЗОВНІШНЕ ЗВ'ЯЗКУ
За замовчуванням усі функції є глобальними. У випадку, якщо вам потрібно приховати деякі функції у файлі ззовні, ви можете встановити статичне ключове слово до функції. :-)
Перш ніж говорити про це питання, краще знати термін одиницю перекладу , програму та деякі основні поняття C ++ (фактично посилання є одним із них загалом). Вам також доведеться знати, що таке сфера застосування .
Наголошу на деяких ключових моментах, особливо ті, які відсутні у попередніх відповідях.
Зв'язок - це властивість імені , яке вводиться декларацією . Різні імена можуть позначати одну сутність (як правило, об'єкт або функцію). Тому говорити про зв'язок суб'єкта господарювання, як правило, нісенітниця, якщо ви не впевнені, що суб'єкт господарювання буде посилатися лише унікальним іменем у деяких конкретних деклараціях (однак, як правило, одна декларація).
Зауважте, що об'єкт - це сутність, але змінна - ні. Говорячи про зв'язок змінної, насправді йдеться про назву позначеної сутності (яка вводиться конкретною декларацією). Зв'язок імені є одним із трьох: відсутність зв'язків, внутрішніх зв'язків чи зовнішніх зв'язків.
Різні одиниці перекладу можуть надавати одне і те ж декларація за заголовком / вихідним файлом (так, це формулювання стандарту). Тож ви можете вказати те саме ім’я в різних підрозділах перекладу. Якщо назва, яке оголошує, має зовнішню зв'язок, то ідентифікатор особи, на яку посилається ім'я, також поділяється. Якщо назва, яке оголошує, має внутрішню зв'язок, те саме ім'я в різних одиницях перекладу позначає різні сутності, але ви можете вказати сутність у різних областях однієї одиниці перекладу. Якщо назва не має зв’язків, ви просто не можете передати об'єкт з інших областей.
(На жаль, я знайшов, що я набрав, дещо просто повторював стандартне формулювання ...)
Існують також деякі інші заплутані моменти, які не охоплені специфікацією мови.
__attribute__
або__declspec
) або параметри компілятора, і зображення - це не вся програма чи об'єктний файл, перекладений з блоку перекладу, тому жодна стандартна концепція не може точно описати це. Оскільки символ не є нормативним терміном в C ++, він є лише деталізацією реалізації, хоча пов'язані розширення діалектів, можливо, були широко прийняті.Правило зв'язування області простору імен const
змінного щось особливе (і в Зокрема , відрізняється від const
об'єкта , оголошеного в області видимості файлу в C мовою , який також має концепцію зв'язування ідентифікаторів). Оскільки ODR застосовується за допомогою C ++, важливо зберігати не більше одного визначення тієї самої змінної або функції, що відбулися у всій програмі, за винятком inline
функцій . Якщо немає такого спеціального правила const
, найпростіше оголошення const
змінної з ініціалізаторами (наприклад = xxx
) у заголовку чи вихідному файлі (часто "файл заголовка"), включеному декількома одиницями перекладу (або включеними однією одиницею перекладу більше, ніж один раз, хоча рідко) в програмі буде порушувати ODR, який змушує використовуватиconst
змінна як заміна деяких об’єктоподібних макросів неможлива.
Я думаю, що внутрішні та зовнішні зв’язки в C ++ дають чітке і стисле пояснення:
Блок перекладу посилається на файл реалізації (.c / .cpp) та всі файли заголовка (.h / .hpp), які він включає. Якщо об'єкт або функція всередині такої одиниці перекладу має внутрішню зв'язок, то цей специфічний символ видно тільки для лінкера в межах цього блоку перекладу. Якщо об'єкт або функція має зовнішній зв'язок, лінкер також може бачити його під час обробки інших одиниць перекладу. Статичне ключове слово при використанні в глобальному просторі імен змушує символ мати внутрішню зв'язок. Ключове слово Extern приводить до символу, що має зовнішню зв'язок.
Компілятор за замовчуванням пов'язує символи таким чином:
Глобальні змінні non-const мають за замовчуванням зовнішні зв'язки
Const глобальні змінні мають внутрішню зв'язок за замовчуванням
Функції мають зовнішню зв'язок за замовчуванням
Зв'язок визначає, чи ідентифікатори, що мають однакові імена, посилаються на один і той же об'єкт, функцію чи іншу сутність, навіть якщо ці ідентифікатори відображаються в різних одиницях перекладу. Зв'язок ідентифікатора залежить від того, як він був оголошений. Існує три типи зв’язків:
Тільки C ++ : Ви також можете мати зв'язок між C ++ та фрагментами коду, що не належить C ++, що називається мовним зв'язком .
Джерело: Зв'язок програми IBM
В основному
extern linkage
змінна видно у всіх файлахinternal linkage
змінна видно в одному файлі.Поясніть: змінні const внутрішньо посилаються за замовчуванням, якщо інше не оголошено зовнішнім
external linkage
const
глобальна змінна єinternal linkage
extern const
глобальна змінна єexternal linkage
Досить хороший матеріал про зв’язок у C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
В C ++
Будь-яка змінна в області файлу, яка не вкладається в клас або функцію, видно в усіх одиницях перекладу програми. Це називається зовнішнім зв’язком, тому що під час посилання ім'я видно посилання, що знаходиться повсюдно, зовнішнє для цього блоку перекладу.
Глобальні змінні та звичайні функції мають зовнішній зв'язок.
Статичне ім'я об'єкта або функції в області файлу є локальним для блоку перекладу. Це називається внутрішньою зв'язком
Посилання стосується лише елементів, які мають адреси у часі посилання / завантаження; таким чином, оголошення класів та локальні змінні не мають зв'язку.