Salta al contenuto
Note per Studenti Tipi, operatori e controllo del flusso in C

Tipi, operatori e controllo del flusso in C

In questa pagina 6

Tipi fondamentali

Tipo Dimensione tipica Intervallo tipico
char 1 byte −128…127 (o 0…255)
short 2 byte −32 768…32 767
int 4 byte circa ±2,1 miliardi (−231…231−1-2^{31} \dots 2^{31}-1)
long 4 o 8 byte
long long 8 byte circa ±9,2⋅1018\pm 9{,}2 \cdot 10^{18}
float 4 byte 7 cifre significative
double 8 byte 15–16 cifre significative

Operatori

Aritmetici + - * / %, confronto == != < <= > >=, logici && || ! (con corto circuito, come and or not in Python), assegnamento = += -= *= /= %=.

Divisione

  • Tra due interi / è divisione intera, troncata verso zero: 7 / 2 == 3, -7 / 2 == -3, -7 % 2 == -1.
  • Basta un operando reale per avere la divisione reale: 7 / 2.0 == 3.5, (double)a / b.
c
int a = 7, b = 2;
double m1 = a / b;            /* 3.0: la divisione intera avviene PRIMA della conversione */
double m2 = (double)a / b;    /* 3.5 */

Conversioni

  • Implicite: negli operatori aritmetici il tipo "più piccolo" viene promosso al più grande (int → long → float → double); char e short diventano int. Nell'assegnamento il valore si converte al tipo della variabile, con possibile perdita (int i = 3.99; → 3).
  • Esplicite (cast): (tipo)espressione.
  • Mescolare int e unsigned nei confronti dà sorprese: -1 < 0u è falso perché -1 diventa un unsigned enorme.

Incremento e decremento

c
i++;        /* i = i + 1 */
x = i++;    /* x prende il valore VECCHIO di i, poi i aumenta */
x = ++i;    /* prima i aumenta, poi x prende il nuovo valore */

Non usare la stessa variabile più volte in un'espressione che la incrementa (i = i++ + 1; è indefinito).

Operatori bit a bit

& (and), | (or), ^ (xor), ~ (not), <<, >> (spostamenti): x << k vale x⋅2kx \cdot 2^k per valori non negativi senza overflow; x & 1 è il bit meno significativo (pari/dispari). Non confondere & con &&.

Espressione condizionale

max = (a > b) ? a : b; equivale al a if a > b else b di Python.

if

c
if (voto >= 18) {
    printf("promosso\n");
} else if (voto >= 15) {
    printf("orale\n");
} else {
    printf("respinto\n");
}

Condizione sempre tra parentesi. Senza graffe, al ramo appartiene una sola istruzione: usare sempre le graffe.

switch

Confronta un'espressione intera (o char) con costanti.

c
switch (op) {
    case '+':
        r = a + b;
        break;
    case '-':
        r = a - b;
        break;
    case '*':
    case 'x':           /* due etichette, stesso codice */
        r = a * b;
        break;
    default:
        printf("operatore sconosciuto\n");
}

Senza break l'esecuzione prosegue nel case successivo (fall-through).

Cicli

c
while (n > 0) {             /* come in Python */
    n /= 10;
    cifre++;
}

do {                        /* corpo eseguito almeno una volta */
    printf("valore positivo: ");
    scanf("%d", &x);
} while (x <= 0);

for (int i = 0; i < n; i++) {   /* inizializzazione; condizione; aggiornamento */
    somma += v[i];
}

Il for del C è un while compatto: for (init; cond; agg) corpo equivale a init; while (cond) { corpo agg; }. Corrisponde a for i in range(0, n) di Python. break e continue come in Python; non esiste l'else dei cicli.

Errori tipici

  • if (x = 5) invece di if (x == 5): assegna 5 e la condizione è sempre vera (il compilatore con -Wall avvisa).
  • ; subito dopo if (...), while (...) o for (...): il corpo diventa l'istruzione vuota.
  • Divisione intera inattesa (1 / 2 == 0), ad esempio nel calcolo di una media.
  • switch senza break.
  • Overflow di int in prodotti o fattoriali: usare long long o controllare i limiti.

Teoria collegata