Operatori
Aritmetici, relazionali, logici, bitwise e l'operatore ternario.
Operatori Aritmetici
| Operatore | Nome | Esempio | Risultato |
|---|---|---|---|
| + | Addizione | 5 + 3 | 8 |
| - | Sottrazione | 5 - 3 | 2 |
| * | Moltiplicazione | 5 * 3 | 15 |
| / | Divisione | 7 / 2 | 3 (intera!) |
| % | Modulo (resto) | 7 % 2 | 1 |
#include <stdio.h>
int main() {
int a = 17, b = 5;
printf("a + b = %d\n", a + b); // 22
printf("a - b = %d\n", a - b); // 12
printf("a * b = %d\n", a * b); // 85
printf("a / b = %d\n", a / b); // 3 (divisione intera!)
printf("a %% b = %d\n", a % b); // 2 (resto)
// Divisione reale: almeno uno deve essere double
printf("a / b (reale) = %.2f\n", (double)a / b); // 3.40
// Operatori di incremento e decremento
int x = 10;
printf("x++ = %d\n", x++); // Stampa 10, poi x diventa 11
printf("x ora = %d\n", x); // 11
printf("++x = %d\n", ++x); // x diventa 12, stampa 12
printf("x-- = %d\n", x--); // Stampa 12, poi x diventa 11
return 0;
}
% è utilissimo: n % 2 == 0 controlla se n è pari. n % 10 dà l'ultima cifra di n. n % k produce valori da 0 a k-1.
Operatori di Assegnamento Composto
Abbreviazioni molto usate per modificare una variabile:
| Operatore | Equivalente a |
|---|---|
| x += 5 | x = x + 5 |
| x -= 3 | x = x - 3 |
| x *= 2 | x = x * 2 |
| x /= 4 | x = x / 4 |
| x %= 3 | x = x % 3 |
Operatori Relazionali
Confrontano due valori e restituiscono 1 (vero) o 0 (falso).
| Operatore | Significato | Esempio | Risultato |
|---|---|---|---|
| == | Uguale a | 5 == 5 | 1 |
| != | Diverso da | 5 != 3 | 1 |
| > | Maggiore di | 5 > 3 | 1 |
| < | Minore di | 5 < 3 | 0 |
| >= | Maggiore o uguale | 5 >= 5 | 1 |
| <= | Minore o uguale | 4 <= 5 | 1 |
= (assegnamento) con == (confronto)! Scrivere if (x = 5) assegna 5 a x e la condizione è sempre vera. Sempre usare == nei confronti.
Operatori Logici
| Operatore | Nome | Descrizione | Esempio |
|---|---|---|---|
| && | AND logico | Vero se ENTRAMBI sono veri | (a>0) && (b>0) |
| || | OR logico | Vero se ALMENO UNO è vero | (a>0) || (b>0) |
| ! | NOT logico | Nega la condizione | !(a == 0) |
#include <stdio.h>
int main() {
int eta = 20;
int ha_patente = 1; // 1 = true, 0 = false
// AND: entrambe le condizioni devono essere vere
if (eta >= 18 && ha_patente) {
printf("Può guidare\n");
}
// OR: almeno una condizione deve essere vera
int pioggia = 0, vento = 1;
if (pioggia || vento) {
printf("Tempo brutto\n");
}
// NOT
int loggato = 0;
if (!loggato) {
printf("Utente non loggato\n");
}
// Short-circuit evaluation:
// Se la prima parte di && è falsa, la seconda NON viene valutata
int n = 0;
if (n != 0 && (10 / n > 1)) { // Sicuro! Non divide per zero
printf("Questo non stampa\n");
}
return 0;
}
Operatori Bitwise (su bit)
Lavorano direttamente sui bit di un valore intero. Fondamentali nella programmazione a basso livello, sistemi embedded e ottimizzazioni.
| Operatore | Nome | Descrizione |
|---|---|---|
| & | AND bit a bit | 1 solo se entrambi i bit sono 1 |
| | | OR bit a bit | 1 se almeno un bit è 1 |
| ^ | XOR bit a bit | 1 se i bit sono diversi |
| ~ | NOT bit a bit | Inverte tutti i bit |
| << | Shift sinistro | Sposta i bit a sinistra (×2 per ogni posizione) |
| >> | Shift destro | Sposta i bit a destra (÷2 per ogni posizione) |
#include <stdio.h>
int main() {
unsigned char a = 0b11001010; // 202 in decimale
unsigned char b = 0b10110101; // 181 in decimale
printf("a = %d (0b11001010)\n", a);
printf("b = %d (0b10110101)\n", b);
printf("a & b = %d\n", a & b); // AND
printf("a | b = %d\n", a | b); // OR
printf("a ^ b = %d\n", a ^ b); // XOR
printf("~a = %d\n", (unsigned char)~a); // NOT
// Shift: veloce per moltiplicare/dividere per potenze di 2
int x = 8;
printf("\n%d << 1 = %d (x2)\n", x, x << 1); // 16
printf("%d << 2 = %d (x4)\n", x, x << 2); // 32
printf("%d >> 1 = %d (/2)\n", x, x >> 1); // 4
// Usare i flag con OR/AND
unsigned char flags = 0;
flags |= (1 << 0); // Imposta bit 0 (FLAG_A)
flags |= (1 << 2); // Imposta bit 2 (FLAG_C)
printf("\nFlags: 0b%d%d%d%d\n",
(flags >> 3) & 1, (flags >> 2) & 1,
(flags >> 1) & 1, (flags >> 0) & 1);
printf("Bit 0 attivo? %s\n", (flags & (1 << 0)) ? "Sì" : "No");
printf("Bit 1 attivo? %s\n", (flags & (1 << 1)) ? "Sì" : "No");
return 0;
}
Operatore Ternario
È un if/else compatto su una sola riga: condizione ? valore_se_vero : valore_se_falso
#include <stdio.h>
int main() {
int a = 10, b = 20;
// Versione con if/else
int max;
if (a > b) max = a;
else max = b;
// Versione compatta con operatore ternario
int massimo = (a > b) ? a : b;
int minimo = (a < b) ? a : b;
printf("Max: %d, Min: %d\n", massimo, minimo);
// Usato in printf direttamente
int n = 7;
printf("%d è %s\n", n, (n % 2 == 0) ? "pari" : "dispari");
int voto = 28;
printf("Voto %d: %s\n", voto, (voto >= 18) ? "PASSATO" : "BOCCIATO");
return 0;
}
Precedenza degli Operatori
Come nella matematica, alcuni operatori hanno priorità maggiore di altri. Usa le parentesi per essere esplicito.
| Priorità | Operatori | Associatività |
|---|---|---|
| Alta | () [] . -> | Sinistra→Destra |
| ! ~ ++ -- (unari) | Destra→Sinistra | |
| * / % | Sinistra→Destra | |
| + - | Sinistra→Destra | |
| << >> | Sinistra→Destra | |
| < <= > >= | Sinistra→Destra | |
| == != | Sinistra→Destra | |
| & | Sinistra→Destra | |
| ^ | Sinistra→Destra | |
| | | Sinistra→Destra | |
| && | Sinistra→Destra | |
| || | Sinistra→Destra | |
| ?: | Destra→Sinistra | |
| Bassa | = += -= *= /= %= | Destra→Sinistra |
Leggi un numero intero e stampa: se è pari o dispari, se è divisibile per 3, se è divisibile per 5, se è divisibile per entrambi (FizzBuzz).
#include <stdio.h>
int main() {
int n;
printf("Inserisci un numero: ");
scanf("%d", &n);
printf("%d è %s\n", n, (n % 2 == 0) ? "PARI" : "DISPARI");
printf("Divisibile per 3? %s\n", (n % 3 == 0) ? "Sì" : "No");
printf("Divisibile per 5? %s\n", (n % 5 == 0) ? "Sì" : "No");
if (n % 3 == 0 && n % 5 == 0) printf("FizzBuzz!\n");
else if (n % 3 == 0) printf("Fizz!\n");
else if (n % 5 == 0) printf("Buzz!\n");
return 0;
}Leggi tre interi a, b, c. Usa l'operatore ternario (senza if/else) per trovare e stampare il massimo tra i tre.
#include <stdio.h>
int main() {
int a, b, c;
printf("Inserisci tre interi: ");
scanf("%d %d %d", &a, &b, &c);
int max = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
printf("Massimo tra %d, %d, %d = %d\n", a, b, c, max);
return 0;
}Leggi un intero positivo. Stampa le potenze di 2 da 2⁰ a 2¹⁰ usando SOLO l'operatore di shift a sinistra << (non usare pow o moltiplicazioni). Poi verifica se il numero letto è una potenza di 2 usando il trucco bitwise: n & (n-1) == 0.
#include <stdio.h>
int main() {
int n;
printf("Inserisci un intero positivo: ");
scanf("%d", &n);
printf("\nPotenze di 2 con shift:\n");
for (int i = 0; i <= 10; i++) {
printf("2^%2d = %d\n", i, 1 << i);
}
if (n > 0 && (n & (n - 1)) == 0) {
printf("\n%d È una potenza di 2!\n", n);
} else {
printf("\n%d NON è una potenza di 2.\n", n);
}
return 0;
}Leggi due interi. Scambia il loro valore usando il trucco XOR (senza usare una variabile temporanea): a ^= b; b ^= a; a ^= b;. Verifica che funzioni stampando prima e dopo.
#include <stdio.h>
int main() {
int a, b;
printf("Inserisci a e b: ");
scanf("%d %d", &a, &b);
printf("Prima: a=%d, b=%d\n", a, b);
// Swap con XOR (senza variabile temporanea)
a ^= b;
b ^= a;
a ^= b;
printf("Dopo: a=%d, b=%d\n", a, b);
return 0;
}Crea un programma che gestisca permessi Unix-style usando 3 bit (r=bit2, w=bit1, x=bit0). Il programma deve: impostare un permesso, rimuovere un permesso, controllare se un permesso è attivo, e stampare la rappresentazione rwx (con - se il bit è 0). Leggi l'input come stringa "rwx", "r--", "rw-", etc.
#include <stdio.h>
#define BIT_R 4 // 0b100
#define BIT_W 2 // 0b010
#define BIT_X 1 // 0b001
void stampa_permessi(unsigned char p) {
printf("%c%c%c\n",
(p & BIT_R) ? 'r' : '-',
(p & BIT_W) ? 'w' : '-',
(p & BIT_X) ? 'x' : '-');
}
int main() {
unsigned char perm = 0;
// Aggiungi lettura ed esecuzione
perm |= BIT_R;
perm |= BIT_X;
printf("Dopo r+x: ");
stampa_permessi(perm);
// Aggiungi scrittura
perm |= BIT_W;
printf("Dopo +w: ");
stampa_permessi(perm);
// Rimuovi esecuzione
perm &= ~BIT_X;
printf("Dopo -x: ");
stampa_permessi(perm);
// Verifica permessi
printf("Lettura attiva? %s\n", (perm & BIT_R) ? "Sì" : "No");
printf("Scrittura attiva? %s\n", (perm & BIT_W) ? "Sì" : "No");
printf("Esecuzione attiva?%s\n", (perm & BIT_X) ? "Sì" : "No");
return 0;
}