7. előadás
Ellenpélda
// VERY hibás version
#include <stdio.h>
char *answer(const char * question) {
char buffer[80]; //Lokális láthatóság, automatikus élettartam
printf("%s\n",question);
gets(buffer); // Első hiba: lehetséges puffer túlcímzés (buffer overflow)
return buffer; // Második hiba: automatikus élettartam vége
// TILOS visszatérni vele
}
int main(){
printf("answer = %s\n", answer("How are you?"));
return 0;
}
Javított verzió:
#include <stdio.h>
char *answer(const char * question) {
static char buffer[80]; //Lokális láthatóság, de statikus élettartam
printf("%s\n",question);
fgets(buffer, 80, stdin); //fgets a gets helyett, megadható a puffer mérete
return buffer;
}
int main(){
printf("answer = %s\n", answer("How are you?"));
return 0;
}
DE ha többször hívjuk meg a függvényt, nem várt kimenetet kaphatunk.
#include <stdio.h>
char *answer(const char * question) {
char * buffer = (char *)malloc(80); //Dinamikus élettartam, heap-en tárolódik.
if(NULL == buffer){
return "No memory";
}
printf("%s\n",question);
fgets(buffer, 80, stdin);
return buffer;
}
int main(){
printf("answer = %s\n", answer("How are you?"));
return 0;
}
DE a dinamikus élettartamú változók nincsenek automatikusan feltakarítva, azt manuálisan kéne megtenni.
Dinamikus élettartam helyett használhatunk:
#include <stdio.h>
char *answer(const char * question, char * buffer, int len) {
if(NULL == buffer){
return "No memory";
}
printf("%s\n",question);
fgets(buffer, len, stdin);
return buffer;
}
int main(){
char buffer[80]; // Megint automatikus élettartam
printf("answer = %s\n", answer("How are you?", buffer, 80));
return 0;
}
Függvények
int f(int x, int y); //Függvény DEKLARÁCIÓ
int f(int, int); //Függvény deklarációban nem kötelező a paraméterek neveit kiírni
int f(void); //Paraméter nélküli függvény
int f(); //Ismeretlen Paraméterű függvény
Végrekurzió - tail recursion
Paraméterátadás
Cím szerinti
Legrégebbi módszer. Az függvény ugyan azt a tárterületet használja, mint a hívó, tehát ha a függvényben módosítjuk a változót, akkor a hívónál is megváltozik.
C-ben nem ez van
Érték szerinti
A változó értékét lemásolja, és megkapja a függvény.
EZ van C-ben
Eredmény szerinti
A függvény végén az eredményt visszamásoljuk a paraméter címére, addig külön memóriát használunk. ADA használ ilyet bizonyos esetekben.
Példa C-ben
void increment(int i){
++i;
printf("i in increment: %d\n", i);
}
void main(){
int i = 0;
increment(i);
increment(i);
printf("i in main: %d\n", i); // i == 0
return 0;
}
Kimenet:
void increment(int * ip){
++*ip;
printf("i in increment: %d\n", *ip);
}
void main(){
int i = 0;
increment(&i);
increment(&i);
printf("i in main: %d\n", i); // i == 2
return 0;
}
Kimenet: