Puntatori e memoria

Puntatori e indirizzi in C e C++

In questa lezione salverai l'indirizzo di una variabile in un puntatore, accederai al valore tramite il puntatore e modificherai la variabile originale.

Introduzione

Un puntatore (pointer) è una variabile che contiene l'indirizzo di memoria di un'altra variabile. L'operatore & ottiene l'indirizzo di una variabile, mentre l'operatore * (chiamato dereferenziazione) accede al valore che si trova all'indirizzo puntato. I puntatori sono uno dei concetti più importanti di C e C++.

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).

Esempi di codice C e C++

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

int main(void) {
    int score = 70;
    int *score_ptr = &score;
    *score_ptr += 5;
    printf("score=%d same-address=%s\n", score,
           score_ptr == &score ? "yes" : "no");
    return 0;
}
Risultato dell'esecuzione
score=75 same-address=yes
C++
Esegui →
main.cpp
#include <iostream>

int main() {
    int score = 70;
    int* score_ptr = &score;
    *score_ptr += 5;
    std::cout << "score=" << score << " same-address="
              << std::boolalpha << (score_ptr == &score) << '\n';
}
Risultato dell'esecuzione
score=75 same-address=true

Confronto tra C e C++

Il puntatore score_ptr contiene l'indirizzo di score, quindi *score_ptr += 5 in realtà aggiunge 5 alla variabile score stessa, che passa da 70 a 75. Il confronto score_ptr == &score conferma che i due indirizzi coincidono. C++ usa ancora i puntatori semplici (raw pointer) quando serve solo accedere ai dati senza gestire la memoria, ma preferisce i riferimenti quando la variabile non può mai essere vuota.

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