Skip to content

I Tipi Fondamentali e gli Interi

“Per avere successo, la pianificazione da sola non è sufficiente. Bisogna anche saper improvvisare.”
— Isaac Asimov, Fondazione

Come anticipato nel primo capitolo, il tipo di un oggetto dichiara al compilatore in che modo quell’oggetto verrà interpretato e utilizzato. Ogni oggetto in un programma C++ deve possedere un tipo.

Questo capitolo esplorerà i tipi fondamentali (noti anche come tipi primitivi o built-in), ovvero i mattoni base del linguaggio disponibili su ogni piattaforma.

I tipi interi memorizzano numeri interi (senza componente frazionaria). In C++ esistono quattro dimensioni principali per gli interi:

  • short (abbreviazione di short int)
  • int
  • long (abbreviazione di long int)
  • long long (abbreviazione di long long int)

Ciascuno di questi può essere con segno (signed, che ammette numeri positivi, negativi e zero) oppure senza segno (unsigned, solo positivi e zero). Di default, se non specificato, un intero è sempre signed.

Le dimensioni in byte dei tipi interi variano a seconda del sistema operativo e dell’architettura. Un caso emblematico è il tipo long:

  • Su architetture a 32-bit, long occupa 4 byte ovunque.
  • Su architetture a 64-bit, long occupa 4 byte su Windows, ma 8 byte su Linux e macOS. Questo scostamento storico è il motivo per cui non dovresti mai presumere la dimensione esatta di un int o di un long quando scrivi codice cross-platform.

Ecco gli specificatori da usare con printf:

  • short ➔ %hd (unsigned: %hu)
  • int ➔ %d (unsigned: %u)
  • long ➔ %ld (unsigned: %lu)
  • long long ➔ %lld (unsigned: %llu)
  • Esadecimale ➔ %x o %X
  • Ottale ➔ %o

Un letterale è un valore fisso e hardcodato direttamente nel codice sorgente. Il C++ supporta quattro notazioni per scrivere i letterali interi:

  1. Decimale: la base standard (es. 42).
  2. Binario: prefisso 0b (es. 0b101010).
  3. Esadecimale: prefisso 0x (es. 0x2A o 0xFF).
  4. Ottale: prefisso 0 (es. 052).

Per migliorare la leggibilità di numeri molto grandi, il C++ permette di usare l’apice singolo ' come separatore delle migliaia (es. 1'000'000), che verrà completamente ignorato dal compilatore.

Di default, un letterale intero (come 42) viene interpretato dal compilatore come int, a meno che non sia troppo grande, nel qual caso passa a long o long long. Per forzare esplicitamente il tipo di un letterale, puoi aggiungere dei suffissi:

  • u o U per unsigned
  • l o L per long
  • ll o LL per long long (Es: 42ULL forza il valore a essere un unsigned long long).

Come facciamo a sapere quanti byte occupa un tipo di dato sulla nostra macchina? Il C++ ci mette a disposizione l’operatore unario sizeof().

L’operatore sizeof non restituisce un int generico, ma un tipo speciale chiamato size_t (disponibile nell’header <cstddef>). size_t è un intero senza segno garantito dal compilatore per essere sufficientemente grande da contenere la dimensione massima in byte di qualsiasi oggetto in memoria.

Per stampare un size_t tramite printf, lo specificatore corretto è %zd.