Organizacija izvornog koda (C)
#fax #cs/prog/c [deo jezika C]
Od izvornog do izvršivog programa
-
PRETPROCESIRANJE — jednostavne zamene u tekstu programa. Objedinjava kod iz različitih datoteka (
#include
) u jedinici prevođenja.gcc -E 1.c
-
KOMPILACIJA
Jedinica prevođenja objektni modul (ne može da se izvrši)- Predni sloj:
- leksička analiza (izdvajanje leksema)
- sintaksička analiza (kreiranje sintaksičkog stabla)
- semantička analiza (transformacija stabla)
- generisanje međukoda ("asemblerski kod")
- Srednji sloj:
- optimizacija međukoda
- Zadnji sloj:
- generisanje ciljnog (mašinskog) koda
- optimizacija ciljnog koda
gcc -c 1.c //rezultat u 1.o
- Predni sloj:
-
POVEZIVANJE — kreiranje jedinstvene izvršive datoteke od jednog ili više objektnih modula (koje su dobiti kompilacijom ili već postoje) — poveziva adrese funkcija i nekih promenljivih.
gcc program -o 1.o 2.c -m //-m za <math.h>
Organizacija koda u više datoteka. make
Izdvajanje neke celine — grupe funkcija u odvojenu datoteku se vrši za:
- kompiliranje jednom i zatim korišćenje objektnog modula
- korišćenje u nekoliko različitih programa
.h
datoteka sadrži deklaracije funkcija odgovarajuće .c
datoteke, deklaracije globalnih promenljivih i definicije struktura.
.c
datoteka sadrži definicije funkcija, deklaracije globalnih promenljivih i konstanti, definicije struktura
Primer:
main.c:
#include "liste.h"
int veci_od(cvor* lista, int broj) {
int count = 0;
while (lista != NULL) {
if (lista->x > broj)
count++;
lista = lista->sl;
}
return count;
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
cvor* lista = NULL;
ucitaj_listu(&lista, n, stdin);
printf("%d\n", veci_od(lista, k));
oslobodi_listu(&lista);
return 0;
}
liste.h:
#ifndef _LISTE_
#define _LISTE_
#include <stdio.h>
#include <stdlib.h>
typedef struct cvor {
int x;
struct cvor* sl;
} cvor;
void greska();
cvor* novi_cvor(int x);
void dodaj_na_pocetak(cvor** pPocetak, int x);
void dodaj_na_kraj(cvor** pPocetak, int x);
void ispisi_listu(cvor* tekuci, FILE* f);
void ucitaj_listu(cvor** pPocetak, int n, FILE* f);
void oslobodi_listu(cvor** pPocetak);
#endif
liste.c:
#include "liste.h"
void greska() {
fprintf(stderr, "-1\n");
exit(EXIT_FAILURE);
}
cvor* novi_cvor(int x) {
cvor* novi = malloc(sizeof(cvor));
if (novi == NULL) greska();
novi->x = x;
return novi;
}
void dodaj_na_pocetak(cvor** pPocetak, int x) {
cvor* novi = novi_cvor(x);
novi->sl = *pPocetak;
*pPocetak = novi;
}
void dodaj_na_kraj(cvor** pPocetak, int x) {
cvor* novi = novi_cvor(x);
novi->sl = NULL;
if (*pPocetak == NULL)
*pPocetak = novi;
else{
cvor* kraj;
for (kraj = *pPocetak; kraj->sl != NULL; kraj = kraj->sl);
kraj->sl = novi;
}
}
void ispisi_listu(cvor* tekuci, FILE* f) {
while (tekuci != NULL) {
fprintf(f, "%d ", tekuci->x);
tekuci = tekuci->sl;
}
printf("\n");
}
void ucitaj_listu(cvor** pPocetak, int n, FILE* f) {
int tekuci, i;
for (i = 0; i < n; i++) {
fscanf(f, "%d", &tekuci);
dodaj_na_kraj(pPocetak, tekuci);
}
}
void oslobodi_listu(cvor** pPocetak) {
cvor* tekuci;
while(*pPocetak != NULL) {
tekuci = *pPocetak;
*pPocetak = (*pPocetak)->sl;
free(tekuci);
}
}
makefile:
program : main.o liste.o
gcc -o program main.o liste.o
liste.o : liste.c liste.h
gcc -c liste.c
main.o : main.c liste.h
gcc -c main.c
make
određuje zavisnost datoteka, tako što
fajl1 : fajle_od_kojih_zavisi_fajl1
gcc kako se kreira fajl
Prvim treba navesti ciljni fajl.
Komandna linija:
make
make
će kreirati stablo zavisnosti i gledajući na vreme poslednjih promena datoteka će izvršavati samo potrebne komande u potrebnom redosledu.
U primeru ako se promenio main.c
, prvo će biti izvršeno gcc -c main.c
da bi se dobio main.o
pa će izvršiti gcc -o program main.o liste.o
.