Cos'è una Variabile?

Una variabile è uno spazio di memoria con un nome. Il tipo di dato determina quanti byte occupa e come viene interpretato il contenuto.

CDichiarazione e inizializzazione
#include <stdio.h>

int main() {
    // Dichiarazione (crea lo spazio in memoria)
    int eta;

    // Inizializzazione (assegna un valore)
    eta = 25;

    // Dichiarazione + inizializzazione in una riga
    int anno = 2024;
    double altezza = 1.75;
    char iniziale = 'M';

    // Costante: non può essere modificata dopo l'inizializzazione
    const double PI = 3.14159265;

    printf("Età: %d, Anno: %d\n", eta, anno);
    printf("Altezza: %.2f m, Iniziale: %c\n", altezza, iniziale);
    printf("PI greco: %.5f\n", PI);

    return 0;
}

Tipi di Dato Fondamentali

TipoDimensione tipicaRangeFormato printf
char1 byte-128 a 127 (o 0 a 255)%c / %d
int4 byte-2.147.483.648 a 2.147.483.647%d
short2 byte-32.768 a 32.767%hd
long4-8 bytedipende dalla piattaforma%ld
long long8 byte±9.223.372.036.854.775.807%lld
float4 byte~±3.4×10³⁸ (7 cifre)%f
double8 byte~±1.7×10³⁰⁸ (15 cifre)%lf / %f
unsigned int4 byte0 a 4.294.967.295%u
Csizeof — dimensioni reali sul sistema
#include <stdio.h>

int main() {
    printf("char:       %zu byte\n", sizeof(char));
    printf("short:      %zu byte\n", sizeof(short));
    printf("int:        %zu byte\n", sizeof(int));
    printf("long:       %zu byte\n", sizeof(long));
    printf("long long:  %zu byte\n", sizeof(long long));
    printf("float:      %zu byte\n", sizeof(float));
    printf("double:     %zu byte\n", sizeof(double));

    return 0;
}
Output (sistema a 64-bit)
char:       1 byte
short:      2 byte
int:        4 byte
long:       8 byte
long long:  8 byte
float:      4 byte
double:     8 byte

Overflow e Limiti

Quando un valore supera il massimo rappresentabile dal tipo, si verifica un overflow: il valore "torna dall'inizio" (comportamento undefined per i signed in C).

CLimiti con limits.h
#include <stdio.h>
#include <limits.h>   // Costanti per i limiti dei tipi interi
#include <float.h>    // Costanti per i limiti dei tipi floating-point

int main() {
    printf("INT_MAX  = %d\n",  INT_MAX);
    printf("INT_MIN  = %d\n",  INT_MIN);
    printf("UINT_MAX = %u\n",  UINT_MAX);
    printf("LLONG_MAX= %lld\n", LLONG_MAX);

    printf("FLT_MAX  = %e\n",  FLT_MAX);
    printf("DBL_MAX  = %e\n",  DBL_MAX);

    // Esempio di overflow (comportamento non definito per signed!)
    unsigned char uc = 255;
    uc++;   // 255 + 1 = 0 per unsigned (ben definito)
    printf("255 + 1 (unsigned char) = %d\n", uc);

    return 0;
}
Attenzione — Overflow L'overflow su tipi signed è undefined behavior in C: il compilatore può fare qualsiasi cosa. Usa unsigned se hai bisogno del wrap-around garantito.

Type Casting (Conversione di Tipo)

Puoi convertire esplicitamente un valore da un tipo all'altro con il cast esplicito, oppure il compilatore lo fa automaticamente (cast implicito).

CCast esplicito e implicito
#include <stdio.h>

int main() {
    int a = 7, b = 2;

    // Divisione intera (risultato: 3, NON 3.5)
    printf("7 / 2 (int)    = %d\n", a / b);

    // Cast esplicito: uno degli operandi diventa double
    printf("7 / 2 (double) = %.1f\n", (double)a / b);

    // Cast implicito: da int a double
    double d = a;          // 7 → 7.0
    printf("int->double: %.1f\n", d);

    // Troncamento: da double a int
    double pi = 3.99;
    int piInt = (int)pi;   // Tronca, NON arrotonda!
    printf("3.99 -> int: %d\n", piInt);

    // char e int sono intercambiabili
    char c = 'A';
    printf("'A' come intero: %d\n", (int)c);  // 65
    printf("65 come char: %c\n", (char)65);    // A

    return 0;
}
Output
7 / 2 (int)    = 3
7 / 2 (double) = 3.5
int->double: 7.0
3.99 -> int: 3
'A' come intero: 65
65 come char: A
Attenzione Il cast da double a int tronca (rimuove i decimali), non arrotonda. 3.99 diventa 3, non 4.

Variabili in C++ — Novità

Il C++ aggiunge funzionalità utili per la gestione delle variabili:

C++auto, bool, string in C++
#include <iostream>
#include <string>    // std::string
using namespace std;

int main() {
    // auto: il compilatore deduce il tipo automaticamente
    auto x = 42;          // int
    auto y = 3.14;        // double
    auto nome = "Mario";  // const char*

    // bool: tipo booleano nativo (assente in C puro)
    bool attivo = true;
    bool chiuso = false;
    cout << "Attivo: " << attivo << "\n";  // stampa 1

    // std::string: gestione avanzata delle stringhe
    string saluto = "Ciao, ";
    string utente = "Mondo";
    string messaggio = saluto + utente + "!";  // concatenazione con +
    cout << messaggio << "\n";

    // cin per input (alternativa a scanf)
    string cognome;
    cout << "Cognome: ";
    cin >> cognome;
    cout << "Hai scritto: " << cognome << "\n";

    return 0;
}
🏋️ Esercizi
Pratica con variabili, tipi e conversioni.
1
Dimensioni sul tuo sistema
Facilesizeof

Scrivi un programma che stampi la dimensione in byte di tutti i tipi fondamentali (char, short, int, long, long long, float, double, long double) sul tuo sistema usando sizeof.

C
#include <stdio.h>

int main() {
    printf("%-15s %s\n", "Tipo", "Byte");
    printf("----------------------------\n");
    printf("%-15s %zu\n", "char",        sizeof(char));
    printf("%-15s %zu\n", "short",       sizeof(short));
    printf("%-15s %zu\n", "int",         sizeof(int));
    printf("%-15s %zu\n", "long",        sizeof(long));
    printf("%-15s %zu\n", "long long",   sizeof(long long));
    printf("%-15s %zu\n", "float",       sizeof(float));
    printf("%-15s %zu\n", "double",      sizeof(double));
    printf("%-15s %zu\n", "long double", sizeof(long double));
    return 0;
}
2
Codici ASCII
Facilechar / int

Scrivi un programma che legga un carattere da tastiera e stampi: il carattere stesso, il suo codice ASCII, il carattere successivo e quello precedente nella tabella ASCII.

Un char è un intero a 8 bit: puoi fare aritmetica su di esso (c+1, c-1).
C
#include <stdio.h>

int main() {
    char c;
    printf("Inserisci un carattere: ");
    scanf(" %c", &c);   // spazio prima di %c per saltare whitespace

    printf("Carattere:   %c (ASCII: %d)\n", c, (int)c);
    printf("Precedente:  %c (ASCII: %d)\n", c-1, (int)(c-1));
    printf("Successivo:  %c (ASCII: %d)\n", c+1, (int)(c+1));

    return 0;
}
3
Divisione con resto
Medioint / cast

Leggi due interi. Stampa: la divisione intera, il resto (%), la divisione in virgola mobile (double). Poi converti il risultato double in int e mostra la perdita di informazione.

C
#include <stdio.h>

int main() {
    int a, b;
    printf("Inserisci due interi: ");
    scanf("%d %d", &a, &b);

    if (b == 0) {
        printf("Errore: divisione per zero!\n");
        return 1;
    }

    printf("Divisione intera: %d / %d = %d\n",  a, b, a / b);
    printf("Resto:            %d %% %d = %d\n", a, b, a % b);

    double risultato = (double)a / b;
    printf("Divisione reale:  %.6f\n", risultato);
    printf("Troncato a int:   %d\n",   (int)risultato);

    return 0;
}
4
Contatore di secondi
Mediolong / calcolo

Leggi un numero di secondi (usa long long). Convertilo in giorni, ore, minuti e secondi rimanenti. Es: 90061 → 1 giorno, 1 ora, 1 minuto, 1 secondo.

Usa l'operatore % (modulo) ripetutamente.
C
#include <stdio.h>

int main() {
    long long totale;
    printf("Inserisci i secondi totali: ");
    scanf("%lld", &totale);

    long long giorni   = totale / 86400;
    long long ore      = (totale % 86400) / 3600;
    long long minuti   = (totale % 3600) / 60;
    long long secondi  = totale % 60;

    printf("%lld secondi = %lld giorni, %lld ore, %lld minuti, %lld secondi\n",
           totale, giorni, ore, minuti, secondi);

    return 0;
}
5
Analisi dei limiti
Difficilelimits.h / overflow

Scrivi un programma che dimostri visivamente l'overflow: prendi INT_MAX e aggiungi 1 (con cast a long long per vedere il vero valore), poi fai lo stesso con unsigned int (UINT_MAX + 1). Infine, calcola quante volte ci sta INT_MAX in LLONG_MAX.

C
#include <stdio.h>
#include <limits.h>

int main() {
    printf("=== Dimostrazione Overflow ===\n\n");

    // INT_MAX + 1 (usando long long per non perdere il valore)
    long long oltre = (long long)INT_MAX + 1;
    printf("INT_MAX          = %d\n",   INT_MAX);
    printf("INT_MAX + 1      = %lld\n", oltre);
    printf("INT_MAX + 1 (int)= %d\n",   INT_MAX + 1);  // overflow!

    printf("\n");

    // unsigned: wrap-around ben definito
    unsigned int u = UINT_MAX;
    printf("UINT_MAX         = %u\n",  u);
    printf("UINT_MAX + 1     = %u\n",  u + 1);  // 0

    printf("\n");

    // Quante volte INT_MAX sta in LLONG_MAX?
    long long quante = LLONG_MAX / INT_MAX;
    printf("LLONG_MAX / INT_MAX = %lld\n", quante);

    return 0;
}