Curs 3 - Pointeri și Alocarea Dinamică a Memoriei în C

Acest curs abordează pointerii în C, tipurile lor și utilizarea acestora pentru alocarea dinamică a memoriei.

1. Pointeri în C

Un pointer este o variabilă care stochează adresa de memorie a unei alte variabile. Sunt esențiali în C pentru manipularea eficientă a datelor și gestionarea memoriei.

a) Declarația și Utilizarea Pointerilor

#include <stdio.h>

int main() {
    int numar = 10;
    int *p = &numar; // Pointer care stochează adresa lui numar
    printf("Valoarea lui numar: %d\n", numar);
    printf("Adresa lui numar: %p\n", &numar);
    printf("Valoarea accesată prin pointer: %d\n", *p);
    return 0;
}

b) Pointeri la Tablouri

Un pointer poate fi folosit pentru a accesa elementele unui tablou.

#include <stdio.h>

int main() {
    int v[] = {10, 20, 30};
    int *p = v; // Pointer la primul element al tabloului
    for (int i = 0; i < 3; i++) {
        printf("Element %d: %d\n", i, *(p + i));
    }
    return 0;
}

c) Pointeri în Funcții

Pointerii pot fi transmiși către funcții pentru a modifica variabile externe.

#include <stdio.h>

void modifica(int *p) {
    *p = 100; // Modifică valoarea la adresa indicată de pointer
}

int main() {
    int x = 5;
    modifica(&x);
    printf("Noua valoare a lui x: %d\n", x);
    return 0;
}

2. Alocarea Dinamică a Memoriei

În C, memoria poate fi alocată dinamic folosind `malloc`, `calloc`, `realloc` și eliberată cu `free`.

a) Alocarea Dinamică a unui Tablou

Funcția `malloc` este utilizată pentru a aloca un bloc de memorie.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *v = (int*) malloc(5 * sizeof(int)); // Alocă memorie pentru 5 int-uri
    for (int i = 0; i < 5; i++) {
        v[i] = i * 10;
        printf("%d ", v[i]);
    }
    free(v); // Eliberarea memoriei alocate
    return 0;
}

b) Alocarea Dinamică a unei Matrici

Pentru matrici, se poate folosi `malloc` pentru fiecare rând.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int **matrice;
    int linii = 2, coloane = 3;
    
    matrice = (int**) malloc(linii * sizeof(int*));
    for (int i = 0; i < linii; i++) {
        matrice[i] = (int*) malloc(coloane * sizeof(int));
    }
    
    for (int i = 0; i < linii; i++) {
        for (int j = 0; j < coloane; j++) {
            matrice[i][j] = i + j;
            printf("%d ", matrice[i][j]);
        }
        printf("\n");
    }
    
    for (int i = 0; i < linii; i++) {
        free(matrice[i]);
    }
    free(matrice);
    
    return 0;
}

c) Reallocarea Memoriei

Dacă este necesară redimensionarea unui bloc de memorie, se folosește `realloc`.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *v = (int*) malloc(3 * sizeof(int));
    v[0] = 1; v[1] = 2; v[2] = 3;
    v = (int*) realloc(v, 5 * sizeof(int)); // Extinderea tabloului
    v[3] = 4; v[4] = 5;
    for (int i = 0; i < 5; i++) {
        printf("%d ", v[i]);
    }
    free(v);
    return 0;
}

Gestionarea corectă a memoriei este crucială în C pentru evitarea memory leaks și a erorilor de segmentare.

Resurse suplimentare: