защо функцията не се нуждае от extern, но променливата има

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

a.cpp

#include <iostream>

using namespace std;

void funcfoo(){
    cout << "test only" << endl;
}

int varfoo = 10;



b.cpp

#include <iostream>

using namespace std;

extern void funcfoo();

extern int varfoo;

int main(){

    funcfoo();

    cout << varfoo;

    return 0;
}

След това го компилирам така "cl b.cpp a.cpp"

Въпросът ми е. Как така, когато премахна „extern ключовата дума преди void funcfoo()“, тя работи добре, но когато премахна extern ключовата дума преди int var foo, получавам грешка?


person user1628256    schedule 27.08.2012    source източник
comment
Вижте stackoverflow.com/questions/2604202/ -- функциите имат външна връзка по подразбиране; ключовата дума е излишна.   -  person Wooble    schedule 27.08.2012


Отговори (4)


Въпросът е какво означава всеки един от редовете на кода. int varfoo е дефиниция на променлива, докато void funcfoo() е само декларация. Можете да предоставите множество декларации на обект, но само една дефиниция. Синтаксисът за предоставяне на декларация и само декларация на променлива е чрез добавяне на ключовата дума extern: extern int varfoo; е декларация


3.1 [basic.def]/2 Декларацията е дефиниция, освен ако не декларира функция без да указва тялото на функцията (8.4), съдържа външния спецификатор (7.1.1) или спецификация на свързване25 (7.5) и нито инициализатор, нито функционално тяло [...]

person David Rodríguez - dribeas    schedule 27.08.2012
comment
Мисля, че дефиницията е като int varfoo = стойност;, след това int varfoo; е декларация. Греша ли? - person user1628256; 27.08.2012
comment
int varfoo; ‹--- Мисля, че това е декларация, а не дефиниция - person user1628256; 27.08.2012
comment
@user1628256: Да. int varfoo; е дефиниция без инициализация, int varfoo = value; е дефиниция с инициализация. - person David Rodríguez - dribeas; 27.08.2012
comment
int varfoo = стойност; ‹---- Мисля, че това е деклариране и след това дефиниране. Греша ли? - person user1628256; 27.08.2012
comment
@user1628256 int var; ‹-- (дефиниция), var = 5; ‹-- дефиниция - person 0x499602D2; 27.08.2012
comment
void funcfoo(){ cout ‹‹ тест само ‹‹ endl; } ‹--- това е дефиниция, нали? - person user1628256; 27.08.2012
comment
Това е определение. Забележка: в глобалния обхват int varfoo; е с инициализация. - person Karoly Horvath; 27.08.2012
comment
@KarolyHorvath: Не съм сигурен в това. Променливите със статична продължителност на съхранение са стойност, инициализирана преди да се извърши всяка друга инициализация, но това не означава, че декларацията има инициализатор (няма такъв). - person David Rodríguez - dribeas; 27.08.2012
comment
така че няма декларация на променлива, а само функция? - person user1628256; 27.08.2012
comment
@user1628256: extern int varfoo; е декларация на променлива. - person David Rodríguez - dribeas; 27.08.2012
comment
добре, нека просто забравим за extern, да кажем, че имаме само 1 .cpp файл... така че int varfoo каза, че е дефиниция, нали? - person user1628256; 27.08.2012
comment
@user1628256: Да, int varfoo; е определение - person David Rodríguez - dribeas; 27.08.2012
comment
@David: защо extern int varfoo; става декларация? - person user1628256; 27.08.2012
comment
@user1628256: Защото така се говори на езика... прочетете цитата от стандарта в отговора. - person David Rodríguez - dribeas; 27.08.2012
comment
@user1628256 Преди да отговоря на този въпрос, можете ли да приемете този отговор, като щракнете върху отметката до него? Много помага. - person 0x499602D2; 27.08.2012
comment
@user1628256: това наистина е объркващо. Чувствам се като с раздвоение на личността (с другия Дейвид). Както и да е: какво не разбра от последния ми коментар? Прочете ли цитата от стандарта? - person David Rodríguez - dribeas; 27.08.2012
comment
@user1628256 Знаете, че това е декларация на променлива, когато видите: int a;. Но това е дефиниция на променлива, когато видите: a = 3 по-късно. Можете също да направите това: int a = 5;. Дефинирам нова променлива, наречена a, която инициализирам с числото 5. Няма значение дали виждате extern отпред. Ако не се инициализира, това е декларация. - person 0x499602D2; 27.08.2012
comment
@david Разбирам декларацията и дефиницията с функция. Цитатът от стандарта, който публикувате, е за функциите, нали? Това, което не разбирам, е относно променливата, която казахте, че int varfoo е дефиниция, а extern int varfoo е декларация. Не разбирам защо с extern става декларация. - person user1628256; 27.08.2012
comment
@user1628256: Не, става въпрос за декларации като цяло. Обърнете внимание, че последното цитирано изречение съдържа: и нито инициализатор, нито тяло на функция. Не можете да предоставите initializer за функция, тъй като не можете да предоставите тяло на функция за променлива. - person David Rodríguez - dribeas; 27.08.2012
comment
@david int varfoo е дефиниция на променлива ‹--- ти каза това - person user1628256; 27.08.2012
comment
@user1628256: Да, int varfoo; е дефиниция и декларация. extern int varfoo; е декларация, но не и дефиниция. Постоянно питаш едно и също, но не разбирам какво те обърква. - person David Rodríguez - dribeas; 27.08.2012
comment
@david Вече знам, че простият отговор на моя въпрос имената на функциите са видими за линкера по подразбиране. Но се обърках с тези дефиниция и декларация. - person user1628256; 27.08.2012
comment
Моля, пренесете този разговор в стаята за чат. -- chat.stackoverflow.com/rooms/10 Или направете свой собствен - person 0x499602D2; 27.08.2012
comment
ти каза int a; е декларация, а по-късно a = 3 е дефиниция. Защо int varfoo е дефиниция, аз нямам стойност. - person user1628256; 27.08.2012
comment
@user1628256: Вие ме бъркате (Дейвид Родригес) с някой друг (Дейвид). Никога не съм казвал, че int a; е декларация (това е, но е и дефиниция). - person David Rodríguez - dribeas; 27.08.2012
comment
@david Знаете, че това е декларация на променлива, когато видите: int a;. Но това е дефиниция на променлива, когато видите: a = 3 по-късно ‹- идва от вас - person user1628256; 27.08.2012
comment
@david добре, въпреки че не го разбирам, искам да ти благодаря. Сега ми се спи, така че може би това е част от причината да не го разбирам. - person user1628256; 27.08.2012
comment
@user1628256: Игнорирайте целия този коментар (имайте предвид, че името на коментиращия е „Дейвид“ -- без фамилни имена в края...) Това е подвеждащо. int a е определение, независимо от = 3. Това е декларация, а не дефиниция, ако и само ако extern присъства и няма инициализатор. - person David Rodríguez - dribeas; 27.08.2012
comment
@KarolyHorvath: Въпросът беше относно коментара Забележка: в глобален обхват int varfoo; е с инициализация. Има малка разлика между наличието на инициализатор и променливата, която се инициализира. Променлива със статична продължителност на съхранение ще бъде инициализирана като стойност, независимо от наличието на инициализатор. Декларацията int varfoo; на ниво пространство от имена не съдържа инициализатор, дори ако е гарантирано, че е инициализирана на 0. - person David Rodríguez - dribeas; 27.08.2012
comment
@David Rodríguez - dribeas: ughmmhuhvomit.. Мисля, че казваш същото, но с правилната терминология. Благодаря. - person Karoly Horvath; 28.08.2012

Когато премахнете extern от extern void funcfoo();, вие го декларирате напред, така че вашият код по-долу ще знае какво е funcfoo(). Ако трябваше да направите това с променлива, вие всъщност ще я инстанциирате и ще влезе в конфликт с другия ви файл. Следователно extern казва „съществува, повярвай ми ;)“, че се разрешава от другия ви файл.

person MartyE    schedule 27.08.2012

Друг начин да мислите за това е, че когато правите int varfoo, паметта се разпределя за съхранение на променливата, така че тя е както дефиниция, така и декларация, когато правите int foo(), функцията е декларирана, но не е дефинирана, така че по някакъв начин паметта не се разпределя. За функциите връзката е външна по подразбиране, така че премахването й няма значение, но за променливата, ако кажете extern int varfoo, компилаторът няма да разпредели памет за нея -- ще приеме, че променливата е дефинирана някъде другаде.

person Vimal Buck    schedule 31.08.2012

Знам, че това може да е късно, но се надявам това да помогне по някакъв начин. Проверете връзката по-долу и тя ще ви даде представа какво е extern и как работи.

http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

Благодаря ти

person nikhs    schedule 16.02.2014