Porkoláb Zoltán - C programozás 2017.11.06. előadás jegyzet
6. előadás: Láthatóság, élettartam szabályai.
1. (scope)
változók, függvények, típusok !azonosítói!
-> a program mely részében mit jelent
2. (life)
-> egy változó (akár a heapben) mettől meddig érvényes (hivatkozhatok rá)
pl. 1. -> globális változó
int glob = 0;
int main(){
glob = 1;
}
// ez statikus élettartamú: a program elejétől a végéig
// alapértelmezetten (implicit) 0-val teszi egyenlővé
pl. ha több forrásfájl: elég egyszer lefoglalni a tárterületet, SŐT!: ha kétszer definiálom-> ambiguous reference
DE: deklarálni kell
extern int glob;
void f(){
int i;
glob++;
}
statikus ill. automatikus élettartam
____________ ____________ _______
| "glob" | "i" |
|____________|____________|_______
statikus automatikus
(stack)
-> minden forrásfájlban
Van egy spec eset:
olyan nevet szeretnénk, ami az adott részben (forrásfájlban) lokálisan statikus
static char buffer[1024];
a másik forrásfájlban lehet:
static int buffer; //nem fog ütközni, de nem is tudom használni
stack szerkezete: mint egy "verem"
-> a fordítóprogram nem név szerint hivatkozik rá, hanem a BÁZISPOINTER-hez képest egy offsetet ad meg
függvényhíváskor: a bázispointer áthelyeződik, a két helyzet közöttre kerül az összes változó
--> STACK-FRAME
a lokális változó is lehet static:
static int k;
az élettartama lesz statikus (a program elejétől a végéig rendelkezésre áll ez a tárterület)
(a láthatósága: marad lokális, szóval csak az adott blokkban nem használhatom újra a nevét)
ha a globális változó static:
a láthatósága: csak ebben a forrásfájlban látható
a globális változó nevével deklarálhatok egy blokkban másik automatikus lokális változót,
ekkor abban a blokkban a lokálist jelenti (a belső változó eltakarta a globálisat)
Dinamikus tárterület (heap)
malloc, free
megmondhatom h mikor foglalom le ill. szabadítom fel
malloc(10*sizeof(int))
--> egy pointert ad vissza
void* (tetszőleges byte-ra mutató pointer)
konvertáljuk int*-ra
int *ip= (int*)malloc(10*sizeof(int));
fel kell szabadítani: különben memory leak, a heap is elfogyhat (nemcsak a stack)
lehetne két lépésben:
void *vp = malloc(10*sizeof(int));
int *ip = (int*)vp;
pointer: tömböt lehet vele indexelni
p[0] //első elem
int t[10]; //tömb
int *ip = t; //az első elemre mutató pointer
int *ip5 = &t[5]; //ez a 5. (6.) elemre mutat
--> ez macerás, ezért kitalálták a pointeraritmetikát:
ip + i //az i. elemre mutat
//(az adott tömb elemei szerint: pl. sizeof(int)-enként)
ip + i == &t[i] //igaz
*(ip+i)==t[i]
*(ip+i) == ip[i] == *(t+i)
__élettartam__:
statikus tár: program elején megmondtam mennyi hely kell
automatikus: adott blokkban lefoglal, utána felszabadít
heap/dinamikus: ha nem szabadítom fel (free), kifogyhatok
--> DE ilyenkor is lehet baj:
lehet h nincs elég nagy ÖSSZEFÜGGŐ tárterület
C#, managed C/C++:
ott a futtató rendszer áthelyezi a pointereket (egybe rakja)
--> hátrány: ez ront a hatékonyságon
_____________________
példa program: kérdez a felhasználótól, és a választ kiírja
#include
char *answer(char *q);
int main(){
printf("%s\n", answer("Hogy vagy?"));
return 0;
}
char *answer(char *q){
char buffer[80];
printf("%s", q);
fgets(buffer, 80, stdin); //nehogy hosszabb legyen (a végén még \0)
return buffer;
} //a gets a hackereké!!!
eddig hibás!!!
--> néha száll el
MERT: a buffer automatikus élettartamú tárterület!!!
a függvényen kívül nem érvényes (life)
nulladik verzió: globális buffer
DE: csak az answer függvénynek kéne látni! -> elhasználtam ezt a nevet
helyette: lokális statikus
#include
char *answer(char *q);
int main(){
printf("%s\n", answer("Hogy vagy?"));
return 0;
}
char *answer(char *q){
static char buffer[80]; //STATIKUS
printf("%s", q);
fgets(buffer, 80, stdin); //nehogy hosszabb legyen (a végén még \0)
return buffer;
}
még nem tökéletes!!!
[
char *q = "Hello"; //ilyenkor lefoglal egy statikus tárterületet
//maga az fgets nem foglal le helyet
//nem lehet "nyújtani" a lefoglalt helyet
]
baj: kétszer meghívva a későbbi hívés maradna benne
printf("%s%s", answer("Hogy vagy?"), answer("Biztos?"));
//ez kétszer kiírná h "Biztos?"
többszálú program: még bajok
globális statikus változók egy időben
több helyről párhuzamosan tudom őket írni, olvasni
Megfelelő kérdés:
Kinek van szüksége a válaszra??
--> itt a main fv-nek
----> ő foglal le
int main(){
char buffer1[80]; char buffer2[80];
printf("%s%s", answer("Hogy vagy?", buffer1, 80), answer("Biztos?", buffer2, 80));
/* ... */
}
char *answer(char *q, char *out, int len){
printf("%s", q);
fgets(out, len, stdin);
return out;
}
még ez se tökéletes: a fordító lehet h felcseréli a paramétereket