Benvenuto nel prontuario delle istruzioni di programmazione in C, progettato per fornirti una guida rapida e schematica ai concetti fondamentali di questo potente linguaggio di programmazione. Questo prontuario ti sarà utile sia se stai iniziando a imparare il linguaggio C sia se hai bisogno di un riferimento veloce mentre lavori ai tuoi progetti.
Indice dei contenuti
Sintassi C
Dichiarazioni di Variabili
- Formato generale:
tipo nomeVariabile;
- Esempi:
int age;
double salary;
char letter;
Funzioni
- Definizione di una funzione:
- Formato:
tipoRitorno nomeFunzione(parametri) { corpo della funzione }
- Formato:
Esempio definizione di una funzione:
int add(int num1, int num2) {
return num1 + num2;
}
Ciclo For:
- Formato:
for (inizializzazione; condizione; incremento) { /* codice */ }
Esempio:
for (int i = 0; i < 10; i++) {
printf("%d\n", i);
}
Ciclo Do-While:
- Formato:
do { /* codice */ } while (condizione);
Esempio:
do {
printf("Il valore è %d\n", val);
val--;
} while (val > 0);
Tipi di dati in C
Tipi di Dati Primitivi
- Interi (
int
): utilizzati per memorizzare numeri interi.int age = 25;
- Carattere (
char
): utilizzato per memorizzare un singolo carattere.char initial = 'A';
- Virgola mobile (
float
,double
):float height = 175.5;
double precision = 0.123456789;
- Vuoto (
void
): indica l’assenza di valore. Usato nei puntatori a void o nelle funzioni che non restituiscono un valore.- Funzione che non restituisce un valore:
void printHello() { printf("Hello\n"); }
- Funzione che non restituisce un valore:
Tipi di Dati Derivati
- Puntatori: utilizzati per memorizzare l’indirizzo di memoria di un’altra variabile.
int* ptr = &age;
- Array: Collezione di elementi dello stesso tipo.
int numbers[5] = {1, 2, 3, 4, 5};
- Strutture (
struct
): consente di raggruppare variabili di tipi diversi.
Esempio strutture
struct Person {
char name[50];
int age;
};
Unioni (union
): permette di memorizzare dati di tipi diversi nello stesso indirizzo di memoria
union Data {
int i;
float f;
char str[20];
};
Funzioni: riferimenti a funzioni che possono essere passati come argomenti ad altre funzioni.
void greet() {
printf("Hello\n");
}
void (*funcPtr)() = greet;
funcPtr();
Operatori in C
Operatori Aritmetici
Utilizzati per eseguire operazioni matematiche comuni.
- Addizione (
+
):a + b
- Sottrazione (
-
):a - b
- Moltiplicazione (
*
):a * b
- Divisione (
/
):a / b
- Modulo (
%
):a % b
(resto della divisione traa
eb
)
Operatori Relazionali
Utilizzati per confrontare due valori.
- Uguale (
==
):a == b
- Non uguale (
!=
):a != b
- Maggiore di (
>
):a > b
- Minore di (
<
):a < b
- Maggiore o uguale a (
>=
):a >= b
- Minore o uguale a (
<=
):a <= b
Operatori Logici
Utilizzati per combinare condizioni booleane.
- AND logico (
&&
):a && b
- OR logico (
||
):a || b
- NOT logico (
!
):!a
Operatori Bit a Bit
Operano direttamente sui bit di operandi interi.
- AND bit a bit (
&
):a & b
- OR bit a bit (
|
):a | b
- XOR bit a bit (
^
):a ^ b
- Complemento a uno (
~
):~a
- Shift a sinistra (
<<
):a << n
(sposta i bit dia
din
posizioni a sinistra) - Shift a destra (
>>
):a >> n
(sposta i bit dia
din
posizioni a destra)
Operatori di Assegnamento
Utilizzati per assegnare valori alle variabili.
- Assegnamento semplice (
=
):a = b
- Assegnamento con addizione (
+=
):a += b
(equivalente aa = a + b
) - Assegnamento con sottrazione (
-=
):a -= b
(equivalente aa = a - b
) - Assegnamento con moltiplicazione (
*=
):a *= b
(equivalente aa = a * b
) - Assegnamento con divisione (
/=
):a /= b
(equivalente aa = a / b
) - Assegnamento con modulo (
%=
):a %= b
(equivalente aa = a % b
)
Gestione della memoria su C
Allocazione dinamica della memoria
Utilizzata per assegnare memoria durante l’esecuzione del programma.
- malloc()
- Uso: alloca uno spazio di memoria di dimensione specificata e restituisce un puntatore a quest’area.
- Esempio:
int* ptr = (int*)malloc(10 * sizeof(int));
- Nota: la memoria allocata con
malloc()
contiene valori indeterminati.
- calloc()
- Uso: alloca spazio per un array di elementi, inizializzando ogni elemento a zero.
- Esempio:
int* ptr = (int*)calloc(10, sizeof(int));
- Nota: a differenza di
malloc()
,calloc()
inizializza la memoria allocata a zero.
Riallocazione della memoria
Utilizzata per modificare la dimensione di un blocco di memoria già allocato.
- realloc()
- Uso: cambia la dimensione di un blocco di memoria precedentemente allocato. Se la nuova dimensione è maggiore, la parte aggiuntiva non sarà inizializzata.
- Esempio:
ptr = (int*)realloc(ptr, 20 * sizeof(int));
- Nota: Se
realloc()
non riesce a estendere il blocco, restituisceNULL
e il blocco originale rimane inalterato.
Deallocazione della memoria
Utilizzata per liberare la memoria precedentemente allocata, evitando così perdite di memoria.
- free()
- Uso: libera la memoria allocata puntata da un puntatore.
- Esempio:
free(ptr);
- Nota: dopo aver chiamato
free()
, il puntatore non dovrebbe essere usato senza essere reinizializzato.
Considerazioni sulla gestione della memoria
- Controllo del valore di ritorno: sempre controllare se le funzioni
malloc()
,calloc()
, erealloc()
restituisconoNULL
, il che indica che l’allocazione della memoria è fallita. - Evitare Memory Leaks: assicurarsi di chiamare
free()
per ogni blocco di memoria allocato dinamicamente non appena non è più necessario.
C: input/output
Input e Output Standard
Queste funzioni sono parte della libreria standard <stdio.h>
, utilizzata per la lettura e la scrittura di input e output standard.
- printf()
- Uso: stampa dati formattati sulla console.
- Esempio:
printf("Età: %d anni\n", age);
- Formato: utilizza specificatori di formato come
%d
(intero),%f
(float),%s
(stringa) per formattare il testo.
- scanf()
- Uso: legge dati formattati dall’input standard (tastiera).
- Esempio:
scanf("%d", &age);
- Formato: simile a
printf
ma usato per l’input. I specificatori di formato devono essere preceduti da&
(indirizzo di) quando si leggono tipi di dati primitivi.
Gestione dei File
Per leggere da file e scrivere su file, C offre funzioni specifiche che permettono un controllo più dettagliato.
- fopen()
- Uso: apre un file in una modalità specificata (es. lettura, scrittura).
- Esempio:
FILE *fp = fopen("file.txt", "r");
- Modalità:
"r"
per lettura,"w"
per scrittura,"a"
per appendere, etc.
- fprintf()
- Uso: stampa dati formattati su un file.
- Esempio:
fprintf(fp, "Nome: %s\n", name);
- fscanf()
- Uso: legge dati formattati da un file.
- Esempio:
fscanf(fp, "%d", &age);
- fclose()
- Uso: chiude un file aperto.
- Esempio:
fclose(fp);
Buffering e controllo di errori
- fflush()
- Uso: pulisce il buffer di output, forzando la scrittura di tutti i dati buffered.
- Esempio:
fflush(stdout);
- Controllo degli errori: funzioni come
ferror()
efeof()
possono essere utilizzate per verificare errori di I/O o il raggiungimento della fine di un file.
Puntatori in C
I puntatori sono variabili utilizzate per memorizzare gli indirizzi di memoria di altre variabili. Sono cruciali per la programmazione in C per gestire la memoria e creare strutture dati complesse.
- Dichiarazione di un puntatore: si dichiara un puntatore specificando il tipo di dati a cui punta, seguito da un asterisco
*
, e il nome del puntatore.- Esempio:
int* ptr;
(puntatore a un intero)
- Esempio:
- Assegnazione di un Indirizzo a un puntatore: utilizza l’operatore
&
per ottenere l’indirizzo di una variabile.- Esempio:
int age = 25; ptr = &age;
- Esempio:
- Dereferenziazione di un puntatore: usa
*
per accedere al valore all’indirizzo memorizzato nel puntatore.- Esempio:
int value = *ptr;
(prende il valore diage
tramiteptr
)
- Esempio:
Operazioni sui puntatori
- Aritmetica dei puntatori: è possibile effettuare operazioni aritmetiche sui puntatori, specialmente con gli array.
- Incremento:
ptr++
(muove il puntatore all’elemento successivo) - Decremento:
ptr--
(muove il puntatore all’elemento precedente) - Differenza:
int diff = ptr2 - ptr1;
(differenza tra due puntatori, utile per calcolare l’offset in un array)
- Incremento:
- Puntatori a puntatori: Puoi avere puntatori che puntano a altri puntatori, utili per creare strutture dati come matrici dinamiche.
- Esempio:
int** ptrPtr;
(puntatore a un puntatore a un intero)
- Esempio:
Puntatori e Array
- Relazione Array-Puntatore: il nome di un array è un puntatore alla sua prima posizione.
- Esempio:
int numbers[10]; int* ptr = numbers;
(ptr punta al primo elemento dinumbers
)
- Esempio:
Puntatori e funzioni
- Passaggio di puntatori a funzioni: i puntatori possono essere passati a funzioni per modificare il contenuto delle variabili passate.
Esempio 1:
void increment(int* value) {
(*value)++;
}
increment(&age);
Ritorno di puntatori da funzioni: le funzioni possono anche restituire puntatori, ma assicurati che il puntatore non punti a variabili locali alla funzione.
Esempio 2:
int* getArray() {
static int arr[10];
return arr;
}
I puntatori sono uno strumento potente in C che permette una gestione efficiente della memoria e la costruzione di strutture dati flessibili. Considera sempre:
- Validità e sicurezza: assicurati sempre che i puntatori puntino a indirizzi validi e siano dereferenziati solo se contengono indirizzi validi.
- Memoria dinamica: i puntatori sono spesso usati con la memoria allocata dinamicamente (
malloc
,calloc
).
Array in C
Gli array in C sono strutture di dati che consentono di memorizzare più elementi dello stesso tipo. Sono utili per la gestione di grandi quantità di dati omogenei.
- Dichiarazione di un Array: specifica il tipo di elementi seguito da parentesi quadre con il numero di elementi.
- Esempio:
int numbers[10];
(array di 10 interi)
- Esempio:
- Inizializzazione di un Array: puoi inizializzare un array al momento della dichiarazione specificando i valori tra parentesi graffe.
- Esempio:
int numbers[5] = {1, 2, 3, 4, 5};
- Esempio:
- Accesso agli Elementi: accedi agli elementi di un array tramite l’indice, che inizia da 0.
- Esempio:
int first = numbers[0];
(accede al primo elemento)
- Esempio:
Operazioni sugli Array
- Iterazione: tipicamente si utilizza un ciclo
for
per iterare sugli elementi di un array.
Esempio iterazione:
for (int i = 0; i < 5; i++) {
printf("%d\n", numbers[i]);
}
- Array Multidimensionali: gli array possono avere più dimensioni, come gli array bidimensionali per matrici.
- Esempio:
int matrix[3][3];
(matrice 3×3 di interi)
- Esempio:
Array e puntatori
- Relazione tra Array e Puntatori: in C, il nome di un array è un puntatore al primo elemento dell’array.
- Esempio:
int* ptr = numbers;
(ptr ora punta al primo elemento di numbers)
- Esempio:
- Aritmetica dei Puntatori con Array: puoi usare l’aritmetica dei puntatori per navigare in un array.
- Esempio:
int secondItem = *(ptr + 1);
(accesso al secondo elemento usando aritmetica dei puntatori)
- Esempio:
Passaggio di Array a funzioni
- Passaggio per riferimento: quando passi un array a una funzione, stai passando un riferimento al primo elemento dell’array.
Esempio:
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
}
printArray(numbers, 5);
Strutture in C
Le strutture in C permettono di raggruppare dati di diversi tipi sotto un unico nome. Sono utili per organizzare dati complessi in modo più strutturato.
- Definizione di una struttura: utilizza la keyword
struct
seguita da un nome opzionale e da un blocco definito da parentesi graffe che include i membri della struttura.
Esempio:
struct Person {
char name[50];
int age;
};
- Dichiarazione di variabili di struttura: puoi dichiarare variabili di tipo struttura specificando il tipo definito.
- Esempio:
struct Person person1;
- Esempio:
- Accesso ai membri di una struttura: utilizza l’operatore
.
per accedere ai membri di una variabile di struttura.- Esempio:
strcpy(person1.name, "Alice"); person1.age = 30;
- Esempio:
Operazioni sulle strutture
- Inizializzazione di strutture: puoi inizializzare una struttura al momento della dichiarazione.
Esempio 1:
struct Person person2 = {"Bob", 28};
Strutture e puntatori: i puntatori a strutture sono spesso usati per gestire le strutture in modo efficiente, specialmente in funzioni.
Esempio 2:
struct Person *ptr = &person1;
printf("%s is %d years old.\n", ptr->name, ptr->age);
Nota: Usa ->
per accedere ai membri tramite puntatori a strutture.
Passaggio di strutture a funzioni
- Passaggio per valore: quando passi una struttura a una funzione per valore, una copia della struttura viene creata.
Esempio 1:
void printPerson(struct Person p) {
printf("%s, %d\n", p.name, p.age);
}
printPerson(person1);
Passaggio per riferimento: passare una struttura per riferimento (tramite puntatori) è più efficiente per strutture grandi.
Esempio 2:
void birthday(struct Person *p) {
p->age += 1;
}
birthday(&person1);
Preprocessore C
Direttive di Base del Preprocessore
Le direttive del preprocessore iniziano con il simbolo #
e sono valutate prima che il programma venga compilato.
- #include
- Uso: Includere file di intestazione o altre sorgenti.
- Esempi:
#include <stdio.h>
(Includi la libreria standard di input/output)#include "myheader.h"
(Includi un file di intestazione definito dall’utente)
- #define
- Uso: Definire macro o costanti simboliche.
- Esempi:
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
(Macro con argomenti)
- #undef
- Uso: Rimuovere definizioni di macro create con
#define
. - Esempio:
#undef PI
- Uso: Rimuovere definizioni di macro create con
Condizionali di Compilazione
Utilizzate per includere o escludere parti del codice durante la compilazione.
- #if, #elif, #else, #endif
- Uso: testare condizioni complesse.
Esempio:
#define DEBUG 1
#if DEBUG
printf("Debug information\n");
#endif
- #ifdef, #ifndef
- Uso: Verificare se una macro è stata definita.
- Esempi:
#ifdef PI
(Esegui se PI è definita)#ifndef PI
(Esegui se PI non è definita)
Altre direttive
- #pragma
- Uso: specificare opzioni di compilazione dipendenti dall’implementazione.
- Esempio:
#pragma once
(Assicura che il file di intestazione venga incluso una sola volta)
- #error
- Uso: generare un errore di compilazione se viene raggiunta una certa condizione.
- Esempio:
#error "Version not supported"
- #line
- Uso: modificare il numero della linea e il nome del file visualizzato nei messaggi di errore del compilatore.
- Esempio:
#line 100 "newfilename"
Librerie in C
Libreria Standard di Input/Output (<stdio.h>)
Fornisce funzionalità per input e output, inclusi la lettura e la scrittura di file.
- Funzioni Principali:
printf()
: Stampa dati formattati all’output standard.scanf()
: Legge dati formattati dall’input standard.fopen()
: Apre un file specificato.fclose()
: Chiude un file aperto.fprintf()
: Stampa dati formattati su un file.fscanf()
: Legge dati formattati da un file.fgets()
: Ottiene una stringa da un file.fputs()
: Scrive una stringa su un file.
Libreria di manipolazione delle stringhe (<string.h>)
Offre funzioni per manipolare stringhe e array di caratteri.
- Funzioni Principali:
strlen()
: Restituisce la lunghezza di una stringa.strcpy()
: Copia una stringa in un’altra.strcat()
: Concatena due stringhe.strcmp()
: Confronta due stringhe.strchr()
: Trova la prima occorrenza di un carattere in una stringa.strstr()
: Trova la prima occorrenza di una sottostringa.
Libreria di gestione della memoria (<stdlib.h>)
Include funzioni per la gestione della memoria dinamica, controllo di processo, conversioni e altro.
- Funzioni Principali:
malloc()
: Alloca un blocco di memoria.free()
: Libera un blocco di memoria allocato.realloc()
: Ridimensiona un blocco di memoria allocato.atoi()
: Converte una stringa in un intero.atof()
: Converte una stringa in un float.exit()
: Termina il processo.
Libreria matematica (<math.h>)
Fornisce funzioni matematiche standard.
- Funzioni Principali:
pow()
: Calcola la potenza di un numero.sqrt()
: Calcola la radice quadrata.sin()
,cos()
,tan()
: Funzioni trigonometriche.log()
: Calcola il logaritmo naturale.exp()
: Calcola l’esponenziale.