Kihagyás

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:

i in increment: 1
i in increment: 1
i in main: 0
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:

i in increment: 1
i in increment: 2
i in main: 2

main paraméterei

int main(int argc, char *argv[]){
    //argv: futtatási paraméterek listája
    //argc: futtatási paraméterek száma

    //Az első paraméter a futtatott program neve
}