Riassunto settimanale · Programmazione I · Canale B · 12/10 – 16/10/2026
Settimana 3: operatori e tipi, scambi, numeri reali, condizioni e if
Il laboratorio e le quattro lezioni della settimana in poche pagine: le divisioni che ingannano, lo scambio fatto bene, come si scrive una condizione che compila con -Wall -Werror, come si segue un programma con gli if, e le domande per controllarti.
- Definizione o risultato da sapere
- Trappola / errore tipico
- Conta all'esame
- Oltre le slide
- Da ricordare
La settimana in 7 punti
- Tra due interi
/dà la parte intera e%il resto:99 / 50fa 1. Basta un reale per avere la divisione con la virgola:99 / 50.0fa 1.98. - Per scambiare due variabili serve una variabile d'appoggio:
temp = x; x = y; y = temp;, in quest'ordine. floatha circa 7 cifre giuste,doublecirca 15. Undoublesi stampa con%fe si legge con%lf.- Mettere un reale in un
inttaglia la parte dopo la virgola. Il cast(double)aconverte quando lo decidi tu. - Un confronto vale 1 se è vero e 0 se è falso. Le condizioni si uniscono con
&&,||e!; «x tra 18 e 30» si scrive18 <= x && x <= 30. - Cortocircuito: se la prima parte di
&&o||basta a decidere, la seconda non viene calcolata. ifesegue un blocco solo se la condizione è vera;elsedà l'altra strada;else ifmette in fila più domande.
Lab02 · Operatori e tipi (lun 12/10, mar 13/10)
Il laboratorio ha sei programmi di partenza da leggere, provare e correggere, poi tre programmi nuovi. Le cose da portarsi via:
| Che cosa | Esempio | Risultato |
|---|---|---|
| divisione tra interi | 99 / 50 e 99 % 50 | 1 e 49 |
| basta un reale | 99 / 50.0 | 1.98 |
overflow di un int | x + 1 con x che vale 2147483647 | un numero negativo, senza avvisi |
| precedenze | 2 + 3 * 4 | 14: *, /, % prima di + e - |
| media di tre interi | (a + b + c) / 3 con 4, 5, 5 | 4: serve 3.0, che dà 4.67 |
| approssimazione | (int)(8.136 * 1000) | 8135, non 8136 |
| dimensione di un puntatore | sizeof(int*), sizeof(double*) | 8 byte tutti e due, su 64 bit |
constdichiara una costante:const double PI = 3.14159;non si può più cambiare.- Per arrotondare ci sono
floor,ceilerounddimath.h; il cast ainttaglia e basta. - In
errori.cgli errori sono 8: il compilatore li segnala uno alla volta, e conviene correggere sempre il primo.
Prova tu
Quanto valgono 17 / 4, 17 % 4 e 17 / 4.0?
4, 1 e 4.25: tra interi la divisione taglia, con un reale no.
Da ricordare
- Tra interi la divisione è intera. Una media si divide per
3.0. - L'overflow degli
intnon dà avvisi: il risultato è sbagliato in silenzio.
03A · Scambiare due variabili (mar 13/10)
Lo scambio «ovvio» x = y; y = x; non funziona: il primo assegnamento cancella il vecchio valore di x, e alla fine le due variabili valgono uguale. Come con due tazze di tè da scambiare, serve una terza tazza vuota.
x = 8 e y = 3. Prima si mette da parte x (1), poi si copia y in x (2), infine si rimette in y il valore messo da parte (3).tempdeve avere lo stesso tipo delle due variabili.- L'ordine conta: con gli stessi tre assegnamenti in un altro ordine un valore si perde di nuovo. La regola: si copia per primo il valore che sta per essere sovrascritto.
- Per scambiare in giro più variabili, come nell'esercizio
scambio4.c, basta una sola variabile d'appoggio.
Prova tu
Con int a = 1, b = 2;, quanto valgono le due variabili dopo temp = a; b = a; a = temp;?
Tutte e due 1. L'ordine è sbagliato: b = a cancella il 2 prima che qualcuno l'abbia messo da parte.
Da ricordare
temp = x; x = y; y = temp;: ogni variabile, a sinistra, è stata letta prima di essere riscritta.- Il compilatore non avvisa se lo scambio è sbagliato: va controllato a mano.
03B · Numeri reali, conversioni e cast (mar 13/10)
I numeri con la virgola in C hanno due tipi, che cambiano per spazio occupato e precisione:
| Tipo | Byte | Cifre giuste | printf | scanf |
|---|---|---|---|---|
float | 4 | circa 7 | %f | %f |
double | 8 | circa 15–16 | %f | %lf |
%fstampa 6 cifre dopo la virgola,%.2fdue,%eusa la notazione scientifica,%gsceglie la più corta.- Sui reali non c'è
%. Radici e potenze sono inmath.h:sqrt,pow. - I reali sono approssimati: non si confrontano con
==. - Promozione: in un'espressione con tipi diversi il più piccolo diventa il più grande, e un intero con un reale dà un reale.
- La divisione che inganna: in
float z = 5 / 2;la divisione è tra interi e fa 2; solo dopo il 2 diventa 2.000000. - Il cast va messo prima della divisione:
(double)a / bdivide con la virgola,(double)(a / b)converte un risultato già tagliato.
Prova tu
Con int a = 9, b = 4;, quanto valgono (double)a / b e (double)(a / b)?
2.25 e 2.0: nel secondo la divisione tra interi è già stata fatta, e il cast converte il 2.
Da ricordare
- Un
doublesi legge con%lf. - Il tipo di una divisione lo decidono i due operandi, non la variabile a sinistra dell'uguale.
03C · Espressioni booleane (mer 14/10)
Un'espressione booleana è una domanda con risposta sì o no: in C vale 1 se è vera e 0 se è falsa. Si confronta con ==, !=, <, >, <=, >=; == confronta, = assegna. Il tipo bool, con true e false, viene da stdbool.h.
a | b | a && b | a \|\| b | !a |
|---|---|---|---|---|
| vero | vero | vero | vero | falso |
| vero | falso | falso | vero | falso |
| falso | vero | falso | vero | vero |
| falso | falso | falso | falso | vero |
Trappola · Due errori che con -Wall -Werror non compilano
0 <= x <= 10si calcola da sinistra e vale sempre 1: gcc lo rifiuta, «comparisons like 'X<=Y<=Z' do not have their mathematical meaning». Si scrive0 <= x && x <= 10.&&dentro||senza parentesi: gcc chiede le parentesi. Le condizioni lunghe si spezzano in variabiliboolcon un nome chiaro.
- Cortocircuito: in
d != 0 && n / d > 5, sedvale 0 la divisione non viene mai fatta. L'ordine dei pezzi conta. - Per negare una condizione si usa De Morgan: il contrario di
a && bè!a || !b. Il!si attacca a una cosa sola:!x > 5vuol dire(!x) > 5. - Ternario:
max = a > b ? a : b;valease la condizione è vera, altrimentib.
Prova tu
Come si scrive la condizione «n non è tra 1 e 100»?
n < 1 || n > 100: per De Morgan è il contrario di 1 <= n && n <= 100.
Da ricordare
- Vero è 1, falso è 0. Un intervallo si scrive con due confronti e
&&. - Il cortocircuito protegge la seconda parte: prima il controllo, poi l'operazione.
03D · Decisioni: if ed else (mer 14/10)
Ogni programma si costruisce con tre strutture: sequenza, selezione e iterazione. Per il teorema di Böhm-Jacopini (1966) bastano per qualunque algoritmo. Questa lezione è la selezione.
if … else: dalla domanda partono due strade, ne viene percorsa una sola, e poi le strade si riuniscono.if (condizione) { … }esegue il blocco solo se la condizione è vera.elseè l'altra strada; conelse ifsi entra nel primo blocco con la condizione vera, e gli altri si saltano. All'esame nienteswitch.- Gli errori più comuni:
=al posto di==e le graffe dimenticate (con-Wall -Werrortutti e due non compilano), le condizioni nell'ordine sbagliato. - Una variabile dichiarata dentro un blocco esiste solo lì: alla
}sparisce dallo stack. - Gli esempi delle slide con
void main()non compilano con-Wall -Werror: si scriveint main(void). - Schemi che tornano sempre: il massimo di due numeri, il controllo del valore restituito da
scanf, la divisione protetta, il controllo di un intervallo.
Prova tu
Con int voto = 24;, quale blocco esegue if (voto >= 18) { … } else if (voto >= 24) { … } else { … }?
Il primo: voto >= 18 è già vera, e gli altri si saltano. Il secondo blocco non viene mai eseguito, perché le condizioni sono nell'ordine sbagliato: la più stretta va messa prima.
Da ricordare
- Con
else ifle condizioni si controllano in ordine, e conta solo la prima vera. - Per seguire un programma con gli if, scrivi i valori delle variabili prima di ogni domanda.
Verso l'esame
- Correttezza di una sequenza di assegnazioni: si ragiona all'indietro dalla post-condizione. Lo scambio con
tempè un esercizio perfetto per allenarsi. - Stato della memoria: una riga per variabile, i valori aggiornati a ogni assegnamento. Attenzione alle conversioni: un
doublemesso in unintperde la parte dopo la virgola. - Programmazione: i test di CodeRunner confrontano le stampe. Una media divisa per
3invece che per3.0, o un%fal posto di%lfinscanf, fanno fallire i test. - Appelli 2026/27: lunedì 25/01/2027 e giovedì 11/02/2027, alle 9:00.
Domande di ripasso
Quanto valgono 99 / 50, 99 % 50 e 99 / 50.0?
1, 49 e 1.98.
Perché x = y; y = x; non scambia le due variabili?
Perché il primo assegnamento cancella il vecchio valore di x: alla fine tutte e due valgono il vecchio y.
Con quale specificatore si legge un double con scanf?
%lf. Con %f scanf scriverebbe un float nella casella di un double.
Che cosa vale float z = 5 / 2;?
2.000000: la divisione è tra interi e fa 2, poi il 2 viene convertito.
Come si scrive in C «x è tra 0 e 10»?
0 <= x && x <= 10.
Perché d != 0 && n / d > 5 non divide mai per zero?
Per il cortocircuito: se d vale 0 la prima parte è falsa, e la seconda non viene calcolata.
Quali sono le tre strutture del teorema di Böhm-Jacopini?
Sequenza, selezione e iterazione.
Quiz d'esame
L'esame di Programmazione I non ha domande a crocette. Ha due esercizi di teoria su CodeRunner, «correttezza di una sequenza di assegnazioni» e «stato della memoria», e tre di programmazione. Le domande qui sotto sono sul modello di questi esercizi, con gli argomenti della settimana: le prime due come l'esercizio «Corr. Ass. 1» della pagina Moodle 2023/24, le altre come lo stato della memoria e gli errori che fanno fallire i test. Ho compilato e provato tutto con gcc 16.1 e -Wall -Werror.
- Sul modello di «Corr. Ass. 1», ragionamento all'indietro. Il programma esegue
temp = x;, poix = y;, poiy = temp;. Alla fine deve valerex == 3 && y == 8. Quale pre-condizione serve all'inizio?All'indietro: prima diy = tempservex == 3 && temp == 8; prima dix = yservey == 3 && temp == 8; prima ditemp = xservey == 3 && x == 8. Lo scambio scambia, quindi all'inizio i valori sono rovesciati. La risposta più insidiosa ètemp == 8 && y == 3: è la condizione a metà strada, ma all'iniziotempnon ha ancora un valore. - Sul modello di «Corr. Ass. 1», con lo scambio sbagliato. Il programma esegue
x = y;e poiy = x;. Alla fine deve valerex == 5 && y == 5. Qual è la pre-condizione più debole?Prima diy = xsi sostituisceyconx:x == 5 && x == 5, cioèx == 5. Prima dix = ysi sostituiscexcony:y == 5. Il vecchio valore dixnon conta, perché viene cancellato subito. La risposta più insidiosa èx == 5 && y == 5: funziona, ma chiede più del necessario. - Sul modello dello stato della memoria. Dopo
int a = 7, b = 2; double m = a / b; double n = (double)a / b; int k = n;quanto valgonom,nek?Ina / btutti e due sono interi: la divisione fa 3, e solo dopo diventa 3.0. In(double)a / bil cast viene prima, quindi la divisione è con la virgola: 3.5. Mettere 3.5 in uninttaglia, non arrotonda: 3. La risposta più insidiosa è quella conm= 3.5: conta il tipo dei due operandi, non quello della variabile a sinistra. - Sul modello dello stato della memoria. Dopo questo codice quanto valgono
xey?int x = 7, y = 3; if (x > y) { int t = x; x = y; y = t; } if (x % 2 == 0) { x = x + 10; } else if (y > 5) { y = y - 5; } else { x = 0; }Il primoifscambia:x= 3,y= 7. Poix % 2vale 1, quindi la prima strada no;y > 5sì, quindiy= 2, e l'elsesi salta. La risposta più insidiosa èx= 3,y= 7: chi pensa che dopo una condizione falsa si salti tutto si ferma al primo blocco.tesiste solo dentro le graffe del primoif. - Sul modello degli errori che fanno fallire i test. Con
int d = 0, n = 10; bool ok = d != 0 && n / d > 5;, che cosa stampaprintf("%d", ok);?d != 0è falso, quindi tutta la congiunzione è falsa e la divisione non viene calcolata: è il cortocircuito.okvale 0. La risposta più insidiosa è il blocco per divisione per zero: succederebbe scrivendon / d > 5 && d != 0, con i pezzi nell'ordine sbagliato. - Sul modello degli errori di compilazione. Con
int x = 50;, che cosa succede compilando congcc -Wall -Werrorun programma che contieneprintf("%d", 0 <= x <= 10);?gcc con-Wallsegnala «comparisons like 'X<=Y<=Z' do not have their mathematical meaning», e-Werrortrasforma l'avviso in errore. La risposta più insidiosa è «stampa 1»: è quello che succede senza opzioni, perché0 <= 50vale 1 e1 <= 10è vero. Con un avviso e basta si compilerebbe solo senza-Werror. - Sul modello degli errori che fanno fallire i test. Dopo
int a = 4, b = 5, c = 5; double m = (a + b + c) / 3;, che cosa stampaprintf("%.2f", m);?(a + b + c) / 3è una divisione tra interi: 14 diviso 3 fa 4, e inmva 4.0. Con%.2fsi stampa 4.00. La risposta più insidiosa è 4.67, che è la media vera: per averla serve/ 3.0. 4 senza decimali non può uscire da%.2f. - Sul modello del Laboratorio 02. Che cosa stampa
printf("%d", (int)(8.136 * 1000));?8.136 in binario non si scrive esattamente: è un po' meno, e8.136 * 1000viene circa 8135.999999. Il cast ainttaglia la parte dopo la virgola: 8135. La risposta più insidiosa è 8136, che sarebbe il risultato con un arrotondamento: per averlo serverounddimath.h.