Prvo treba da razlikuješ deklaracije od definicija. Deklaracija promenljive određuje njeno ime i tip, a definicija sve to i još rezerviše memorijski prostor u objektnom fajlu (.obj kod MSVC). Deklaracija funkcije određuje njeno ime, broj i tip argumenata u navedenom redosledu i tip povratne vrednosti. Definicija funkcije osim toga sadrži i telo, tj. određuje šta i kako funkcija radi, za šta je potrebno rezervisanje memorijskog prostora u objektnom fajlu. Definicije makroa i tipova su zapravo deklaracije jer ne zauzimaju memorijski prostor.
Drugo što treba da znaš je šta su jedinice za prevođenje. Jedinica za prevođenje se sastoji od tačno jednog .c fajla i svih .h fajlova koje on uključuje #include direktivama. Pritom, ako fajl modul.c uključuje zaglavlje modul.h koje uključuje zaglavlje bib.h, onda se smatra da modul.c takođe uključuje fajl bib.h. Jedinica za prevođenje u jednom projektu ima tačno onoliko koliko i .c fajlova. Sa druge strane, tipično je svaki od .h fajlova deo više jedinnica za prevođenje u projektu. Jedinica za prevođenje se prevodi naredbom za prevođenje kojoj se zadaje odgovarajući .c fajl. Na taj način se dobija tačno onoliko objektnih fajlova koliko ima jedinica za prevođenje, odnosno tačno onoliko koliko ima .c fajlova. Na kraju se svi objektni fajlovi povezuju u jedan izvršni fajl (.exe, .lib ili .dll kod MSVC). Ceo postupak prevođenja je automatizovan kod većine okruženja u koje spada i MSVC.
U zaglavlja (.h fajlove) se stavlja tačno ono što treba da bude vidljivo iz više jedinica za prevođenje, pri čemu se ništa ne stavlja u više od jednog zaglavlja i pri čemu se u zaglavlaj nikada ne stavljaju definicije koje zauzimaju memorijski prostor, tj. definicije promenljivih i funkcija. Memorijski prostor se rezerviše u tačno jednoj jedinici za prevođenje u programu u .c fajlu. Ukoliko funkcija ili promenljiva treba da bude vidljiva iz više jedinica za prevođenje, njenu deklaraciju stavljamo u odgovarajuće zaglavlje, a definiciju u odgovarajući .c fajl. Ukoliko definicija makroa ili tipa treba da bude vidljiva iz više jedinica za prevođenje, stavljamo je u odgovarajuće zaglavlje i nigde više. Sve što ne treba da bude vidljivo iz više jedinica za prevođenje, stavljamo isključivo u odgovarajući .c fajl.
Uobičajeno je da zaglavlja predstavljaju logičke celine i da ako u zaglavlju ima deklaracija nečega što zahteva memorijski prostor, da se to definiše u istoimenom .c fajlu. Sa druge strane, nije uobičajeno da se u fajlu u kome se definiše main funkcija definiše bilo šta što ne treba da bude vidljivo u drugim jedinicama za prevođenje. Takođe, uobičajeno je da se svako zaglavlje ogradi zaštitnim direktivama protiv višestrukog uključivanja. Recimo, fajl library.h bi trebao da počinje sa
Code:
#ifndef LIBRARY_H
#define LIBRARY_H
a da se završava sa
Code:
#endif
koje odgovara prvoj #ifndef direktivi (ako u zaglavlju ima više #if* direktiva, uobičajeno je da svaka ima svoj #endif u istom zaglavlju)
MSVC dopušta i stavljanje direktive
Code:
#pragma once
ali ta pragma direktiva nije pokrivena C standardom, tako da neće raditi na drugim prevodiocima.
Jedno od mogućih rešenja tvog zadatka je
fajl main.c:
Code:
#include <stdio.h>
#inlcude "bib.h"
int a=2, b=3, c;
int main()
{
f();
printf("%d\n", c);
return 0;
}
fajl bib.h:
Code:
#ifndef BIB_H
#define BIB_H
extern int a, b, c;
void f();
#endif
fajl bib.c
Code:
#include "bib.h"
void f()
{
c = a + b;
}
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.