CodeGym /Corsi /C++ SELF /Compilatore e commenti

Compilatore e commenti

C++ SELF
Livello 1, Lezione 5
Disponibile

1. Introduzione al compilatore

Il computer non capisce il linguaggio umano. Il computer non capisce nemmeno direttamente i linguaggi di programmazione. Capisce solo i programmi scritti in codice macchina — costituiti da zeri e uni. Le persone invece pensano con parole e idee e, naturalmente, è difficile per loro scrivere interi programmi usando solo 0 e 1.

00100100 si traduce come numero decimale 36 o come carattere $

Per questo sono nati linguaggi di programmazione come C++. Sono una sorta di "traduttori": ora il programmatore può scrivere comandi “Fai questo e quello” in un linguaggio che gli è comprensibile, invece di una lunga sequenza di istruzioni per la CPU.

Ma c'è un problema. Il computer comunque non capisce C++! Se gli dai semplicemente un file di codice, non farà nulla. Proprio per questo motivo esiste il compilatore.

Cos'è esattamente un compilatore?

Il compilatore è un programma speciale che compila il codice: traduce il codice C++ in codice comprensibile al computer. Prende il testo in C++, lo analizza, verifica la presenza di errori e lo trasforma in codice macchina (di solito — sotto forma di file eseguibile).

  • Programma in linguaggio C++
  • Compilatore
  • Programma costituito da codici macchina
Fasi di compilazione per il linguaggio C++

Puoi immaginare il compilatore come un insegnante severo che:

  • controlla attentamente le frasi (hai commesso un errore?),
  • fa rispettare le regole (per esempio nomi di variabili corretti, punti e virgola, parentesi…),
  • e solo dopo permette di parlare con il computer!

Il compilatore è ancora più intelligente

I compilatori C++ oggi sono ancora più intelligenti — possono non solo tradurre, ma anche ottimizzare il codice, segnalare errori e perfino suggerire come scrivere meglio (tramite warning — warnings). E molte altre cose.

Inoltre, per comodità e per una corretta build di programmi complessi, la compilazione di solito non avviene “in un solo passo magico”, ma almeno in più fasi:

  • Prima il preprocessore elabora direttive come #include.
  • Poi il compilatore traduce il codice C++ in codice oggetto (pezzi parziali del programma).
  • E infine il linker (collegatore) unisce questi pezzi e le librerie in un singolo file eseguibile.

Se hai una CPU potente e hai attivato le ottimizzazioni, il compilatore può generare codice macchina tenendo conto delle caratteristiche della tua piattaforma e delle opzioni di build scelte. Ma l'idea principale da ricordare è semplice: C++ viene solitamente compilato direttamente in codice macchina, e solo dopo questo file eseguibile viene eseguito.

       flowchart TD
    SRC["Codice sorgente .cpp files"]:::source

    PP["Preprocessore Elabora #include e #define"]:::stage
    CC["Compilatore Traduce C++ → codice oggetto Trova errori, dà warnings"]:::stage
    LN["Linker Unisce codice oggetto + collega librerie"]:::stage

    EXE["File eseguibile .exe"]:::artifact

    RUN(["▶ Esecuzione Codice macchina pronto viene eseguito direttamente"]):::run

    LIB["Librerie"]:::lib
    DEV["Sviluppatore corregge gli errori"]:::dev

    SRC --> PP --> CC --> LN --> EXE --> RUN
    CC -.->|"⚠️ warnings & errori"| DEV
    LIB --> LN

    classDef source fill:#f59e0b,color:#1c1917,stroke:none
    classDef stage fill:#3b82f6,color:#fff,stroke:#1d4ed8,stroke-width:2px
    classDef artifact fill:#8b5cf6,color:#fff,stroke:#6d28d9,stroke-width:2px
    classDef lib fill:#64748b,color:#fff,stroke:none
    classDef run fill:#22c55e,color:#fff,stroke:none
    classDef dev fill:#fde68a,color:#1c1917,stroke:#f59e0b,stroke-width:1px
   
Questo è uno schema semplificato per comprendere l'idea generale.

2. Errori in fase di compilazione

Velocità e ottimizzazione del codice non sono al momento la nostra priorità; ciò che invece conta è che il compilatore controlla il tuo programma alla ricerca di errori. Verifica la correttezza del codice e non lo lascerà procedere se trova anche un piccolo errore.

Esempio di errore:

Stai cercando di assegnare un numero a una variabile che può contenere solo testo.

#include <string>

int main() {
    std::string userName = 42; // Ops! Non si può fare.
}

Il compilatore segnalerà immediatamente un errore di tipi (la formulazione dipende dal compilatore), qualcosa come: “nessuna conversione adeguata da int a std::string”.

Un altro esempio — un refuso nel nome std::cout:

#include <iostream>

int main() {
    std::coutt << "Ciao!\n"; // Errore nel nome
}

Il compilatore dirà qualcosa come: «coutt non è un membro di std» — controlla la sintassi!

Come leggere gli errori?

La maggior parte dei compilatori indica dove si trova l'errore nel codice: solitamente il file, il numero di riga e spesso anche il numero di colonna, più il testo dell'errore. Non avere paura degli errori: ciascuno di essi è un passo verso l'illuminazione e il superamento del tuo “boss” interno.

3. Errori tipici di compilazione

expected significa: «mi aspettavo di trovare qui il simbolo X, ma non c'è». Più spesso questo accade per:

expected ';' — dimenticato il punto e virgola

Codice rotto:

#include <iostream>

int main() {
    std::cout << "Hello!\n"
    return 0;
}

L'istruzione deve terminare con ;. Il compilatore è arrivato a return e stava ancora aspettando il ;. Correzione:

std::cout << "Hello!\n";

expected '}' — blocco non chiuso

Se dimentichi }, il compilatore di solito segnala l'errore alla fine del file.

int main() {
    std::cout << "Start\n";
    return 0;
// manca }

Basta chiudere il blocco:

}

Consiglio: allinea le indentazioni — è più facile individuare una parentesi mancante.

expected ')' o expected '(' — problema con le parentesi

int main( {

Si deve scrivere:

int main() {

Le parentesi devono aprirsi e chiudersi a coppie.

not declared — nome non trovato

Il compilatore scrive: «non so cos'è questo». Hai dimenticato std::

cout << "Hi\n";

Serve:

std::cout << "Hi\n";

cout si trova nello spazio dei nomi std.

Hai dimenticato #include <iostream>

int main() {
    std::cout << "Hi\n";
}

Aggiungi:

#include <iostream>

Senza #include il compilatore non è obbligato a sapere cosa sia std::cout.

4. Commenti

Sto leggendo il codice di quella persona che affermava: «Il mio codice non ha bisogno di commenti, è già chiaro».

Immagina di scrivere un programma complesso. Tutto funziona, sei un genio! Ma un mese dopo apri quel codice e... non capisci nulla. Due righe qua, una variabile strana là. Ti senti solo: «Sicuramente questo l'ha scritto qualcun altro, non io!». Ed è qui che i commenti ti salvano.

I commenti sono come appunti a margine di un libro o etichette sul frigorifero ("Birra. Non bere. Per domani!"). Il compilatore li ignora, mentre le persone li leggono. I commenti permettono di spiegare il senso del codice, segnare dettagli importanti e perfino "disattivare" parti di programma senza cancellarle.

Importante: il compilatore non “capisce il significato” dei tuoi commenti — per lui sono solo testo da saltare.

Commenti a riga singola

In C++ ci sono due tipi di commenti — a riga singola e multilina. I commenti a riga singola iniziano con doppio slash // e continuano fino alla fine della riga. Tutto ciò che segue // è considerato commento e viene completamente ignorato dal compilatore.

Esempio:

#include <iostream>

int main() {
    std::cout << "Ciao, mondo!\n"; // Questo stampa un saluto sullo schermo
}

Qui // Questo stampa un saluto sullo schermo è un commento. Se una riga di codice ti sembra non chiara, scrivi così!

Altro esempio:

int main() {
    int x = 42; // Valore dell'età del programmatore
}

Puoi anche scrivere commenti a riga singola su linee separate:

#include <string>

int main() {
    // Inizializzazione della variabile con il nome utente
    std::string userName = "Vasya";
}

Quasi come battute in una sceneggiatura: il commento spiega il perché della riga.

Commenti multilina

Se hai molto da dire? Una vera storia? Per questo esistono i commenti multilina, che iniziano con /* e finiscono con */. Tutto ciò che è tra questi simboli viene ignorato dal compilatore, anche se occupa più righe.

Esempio:

#include <iostream>

int main() {
    /*
      Qui mostriamo un suggerimento all'utente.
      Se il nome manca, in altri programmi si può usare "Guest".
    */
    std::cout << "Inserisci il tuo nome:\n";
}

O così:

int main() {
    int age = 18; /* Valore iniziale dell'età
                     per un nuovo utente */
}

Attenzione: non si possono annidare commenti multilina l'uno dentro l'altro. Non cercare di essere più furbo del compilatore — non funzionerà.

Illustrazione:

Tipo Sintassi Esempio
Riga singola
// commento
int x = 1; // spiegazione
Multilina
/* varie cose */
/* qui puoi spiegare tutto quello che vuoi */

5. Esempi dalla vita reale

"Disattivare" una riga di codice:

Capita di voler temporaneamente non eseguire un frammento di codice. I commenti sono perfetti per questo:

// std::cout << "Testo temporaneamente non necessario\n";

La riga rimane, ma il compilatore non la "vede".

Tag TODO e FIXME

I programmatori sono persone anche loro, e talvolta bisogna ricordarsi che il codice non è ancora finito o che c'è un bug. Per questo spesso si scrive:

// TODO: aggiungere il controllo per input vuoto
// FIXME: questa funzione calcola male la somma

Molti editor e IDE evidenziano queste parole!

I programmatori scherzano

E, naturalmente, a volte nei commenti si trovano frasi molto divertenti:

// Non sono responsabile per questo codice. Mi hanno costretto a scriverlo contro la mia volontà.
// Caro, vengo dal futuro! Per favore, perdonami per questo codice.
// Se vedrò ancora una cosa simile, dovrò iniziare a portare un'arma al lavoro.
// Se questa condizione si verifica, per favore contattami al tel. xxx-xx-xx per una ricompensa.
// Caro programmatore:
//
// Quando finirai di "ottimizzare" questa subroutine
// e capirai quanto sia stato un errore enorme farlo,
// per favore aumenta il contatore qui sotto come avvertimento
// per il prossimo ragazzo:
//
// numero_ore_spese_qui = 42
// Quando ho iniziato a scrivere questo, solo Dio e io sapevamo cosa stessi facendo. 
// Ora è rimasto solo Dio
// A volte ho l'impressione che il compilatore ignori tutti i miei commenti
// Dedico tutto il mio codice, tutto il mio lavoro a mia moglie Darlin, che
// dovrà mantenermi, i nostri tre figli e il cane, quando
// questo andrà in produzione.

Sì, i commenti possono essere molto divertenti. Alla fine sono scritti da persone in carne e ossa.

1
Compito
C++ SELF, livello 1, lezione 5
Bloccato
Il punto mancante
Il punto mancante
1
Compito
C++ SELF, livello 1, lezione 5
Bloccato
Il cout smarrito
Il cout smarrito
1
Compito
C++ SELF, livello 1, lezione 5
Bloccato
Disattivare il debug
Disattivare il debug
1
Compito
C++ SELF, livello 1, lezione 5
Bloccato
Catena di guasti
Catena di guasti
1
Sondaggio/quiz
Primo programma, livello 1, lezione 5
Non disponibile
Primo programma
Primo programma
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION