къде ще бъде дефинирана външна декларирана променлива?

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

//globalheader.h//

extern int test_var;

//file1.c//
#include "globalheader.h"

static fn1();
fn1
{
   int a;
   a = test_var;
}

//file2.c//
#include "globalheader.h"

static fn2();
fn2
{
   int b = 1;
   test_var = b;
}

В горния кодов фрагмент test_var е деклариран с външна връзка в globalheader.h, който е включен във file1.c и file2.c. Не къде тази test_var е дефинирана, но се използва, така че къде (в кой обектен файл) тази test_var ще бъде разпределена памет?


person Opener    schedule 06.12.2013    source източник
comment
В изходния файл, който го дефинира, може да пропуснете някои файлове.   -  person moeCake    schedule 06.12.2013
comment
Не се дефинира автоматично никъде, докато обратното е вярно: дефиницията също декларира елемента (и през повечето време дефиницията не трябва да е в конфликт с по-ранна декларация)   -  person Aki Suihkonen    schedule 06.12.2013


Отговори (4)


Вашият test_var не е дефиниран никъде, така че няма да съществува в нито един от вашите обектни файлове и ще получите грешка при свързване, посочваща, че test_var липсва, ако извършите връзка.

Вие сте отговорни за дефинирането му в една от вашите компилационни единици и то ще бъде в който и да е обектен файл, който решите, и зависи от линкера най-накрая да реши всяко място в паметта.

Обърнете внимание, че ако компилирате този конкретен код с оптимизация, компилаторът може да разбере, че статичните ви функции fn1/fn2 никога не се извикват и да ги елиминира изцяло, в който случай няма да има код, който използва test_var.

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

person nos    schedule 06.12.2013

Ключовата дума "extern" само информира компилатора, че мястото в паметта е достъпно за дадената променлива, така че не разпределяйте нова област от паметта. Поради това, когато компилирате file1.c и file2.c, съответният обектен код няма да съдържа областта на паметта. Можете също така да забележите размера на обектния файл. ако сте декларирали която и да е променлива като extern, тогава размерът на обекта няма да бъде увеличен за тази променлива и след като премахнете extern и прекомпилирате, тогава размерът на обекта ще се увеличи. По време на свързването линкерът ще търси обектния файл, където е дефинирана област на паметта за тази променлива (която е дефинирана като extern в други файлове) от дадените обектни файлове. Според вашия код, вие не сте дефинирали променливата никъде, така че областта на паметта за променливата test_var не е разпределена никъде, така че по време на свързването линкерът ще изведе грешка "недефинирана референтна test_var".

person rajenpandit    schedule 06.12.2013

Не сте казали в кой обектен файл искате да живее променливата, така че линкерът трябва да откаже да свърже вашия код. Някои стари линкери може да позволяват това, но би било много по-добре да дефинирате изрично променливата.

person Rob    schedule 06.12.2013
comment
Не, никъде не е дефинирано, само декларирано. Това няма как да успее да се свърже. - person ; 06.12.2013
comment
Това зависи от линкера. Работил съм със стари линкери, които позволяват това. Промених отговора си. - person Rob; 06.12.2013

Когато декларирате променлива като extern, тя трябва да съществува в друг файл. В този случай линкерът ще даде грешка, ако това не е така.

Все пак има изключение в C (което не съществува int C++). Ако на променливата също е присвоена стойност, тя също ще бъде декларирана.

Ако напишете:

 extern int var;

и var не съществува в някой друг модул, той ще се провали.

Ако напишете:

 extern int var = 0;

и var не съществува в някой друг модул, той ще успее.

Очевидно променливата ще се намира във файла, където е декларирана.

person Devolus    schedule 06.12.2013