Puntatori e memoria

Array multidimensionali in C e C++

In questa lezione scorrerai una matrice bidimensionale e calcolerai la somma degli elementi di ogni riga.

Introduzione

Un array bidimensionale si può immaginare come una tabella di righe e colonne. In C e C++ viene memorizzato in modo continuo, riga per riga (row-major): prima tutta la prima riga, poi la seconda, e così via.

Punti importanti

  • Un puntatore deve puntare solo a un oggetto che esiste ancora, del tipo giusto, oppure essere nullo.
  • Ogni area di memoria allocata va liberata esattamente una volta.
  • Rendi chiaro quale funzione possiede la memoria (ownership) e quali dati sono solo letti (const).

Guarda come funziona

Punta una cella per vedere riga, colonna e posizione in memoria, dove tutte le righe sono salvate una dopo l'altra.

Esempi di codice C e C++

C
Esegui →
main.c
#include <stdio.h>

int main(void) {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    for (int row = 0; row < 2; ++row) {
        int total = 0;
        for (int column = 0; column < 3; ++column) total += matrix[row][column];
        printf("row %d=%d\n", row, total);
    }
    return 0;
}
Risultato dell'esecuzione
row 0=6
row 1=15
C++
Esegui →
main.cpp
#include <array>
#include <iostream>

int main() {
    std::array<std::array<int, 3>, 2> matrix{{{{1, 2, 3}}, {{4, 5, 6}}}};
    for (std::size_t row = 0; row < matrix.size(); ++row) {
        int total = 0;
        for (int value : matrix[row]) total += value;
        std::cout << "row " << row << '=' << total << '\n';
    }
}
Risultato dell'esecuzione
row 0=6
row 1=15

Confronto tra C e C++

Due cicli annidati scorrono la matrice: quello esterno passa per ogni riga, quello interno somma gli elementi di quella riga nella variabile total. In C, quando passi un array bidimensionale a una funzione, devi indicare la dimensione di tutti gli assi tranne il primo. In C++, std::array conserva la dimensione nel tipo stesso e ha il metodo at(), che controlla se l'indice è valido.

C

Il possesso e la liberazione della memoria sono interamente a carico del programmatore.

C++

Contenitori e RAII liberano automaticamente le risorse quando l'oggetto arriva alla fine della sua vita.

Esercizi di approfondimento

Esegui entrambe le versioni e poi modifica il codice per osservare la differenza di sicurezza che offre ciascun linguaggio.

  • Prova con puntatori nulli e allocazioni di memoria fallite.
  • Esegui il programma con AddressSanitizer e UndefinedBehaviorSanitizer per trovare errori di memoria.
  • Annota chiaramente quale puntatore possiede la memoria e quale serve solo per leggere.

Esercitati con una sfida

Usa ciò che questa lezione spiega per risolvere un problema reale. Ogni sfida gira nel browser, con test immediati e una revisione dell'IA.

Tutte le sfide