Impara a programmare da zero: Guida utile per iniziare

La programmazione rappresenta il linguaggio con cui comunichiamo con i computer. Programmare ci da la possibilità di accedere ad un’ampia gamma di opportunità nel mondo digitale e ad avere un maggiore controllo e consapevolezza sull’uso degli strumenti digitali. In questo scenario, saper programmare non solo permette di creare nuovi software e soluzioni innovative, ma aiuta anche a sviluppare capacità come il problem solving, affinare un pensiero critico ed espandere la propria creatività.

In questo articolo esploreremo i principi che stanno alla base di ogni linguaggio di programmazione, cercando di dare più nozioni possibili per raggiungere l’obbiettivo di imparare a programmare. Se ti stai chiedendo “Ci sono più linguaggi di programmazione?” La risposta è: decisamente si! Con il tempo sono stati creati diversi linguaggi ognuno con una propria sintassi, ma in linea generale tutti i linguaggi condividono gli stessi principi.

Oggi vedremo le basi che contraddistinguono tutti i linguaggi di programmazione e lo faremo parlando del C, un linguaggio storico che ha plasmato l’informatica e si adatta bene alla didattica per diversi motivi. In primo luogo, C è considerato un linguaggio “di medio livello”, il che significa che combina elementi di linguaggi ad alto e basso livello, rendendolo accessibile e ideale alla didattica ma anche abbastanza potente da essere utilizzato per sviluppare software complessi.

Sistema binario e matematica booleana

Alla base del funzionamento dei computer e in generale della tecnologia digitale vi è il sistema di numerazione binario, formato dalle sole cifre 0 e 1. Grazie alla combinazione di soli due numeri, informazioni come: testi, immagini, suoni e tanto altro, possono essere elaborati e memorizzati in piccoli dispositivi che possiamo portare sempre con noi.

Il sistema numerico binario ha un’applicazione fisica nell’informatica, infatti viene usato per rappresentare gli stati di “acceso/spento” all’interno dei circuiti logici. Il computer è un complesso sistema di algoritmi basato su condizioni logiche matematiche e l’algebra booleana fornisce gli strumenti concettuali necessari per comprendere come i computer elaborano e manipolano i dati utilizzando il sistema binario.

Vediamo subito insieme quali sono le operazioni booleane fondamentali:

  • AND – entrambe le condizioni devono essere vere affinché l’azione si verifichi;
  • OR – una delle due condizioni deve essere vera;
  • NOT – la condizione deve avere un valore opposto per essere vera;

Immaginate di dover scrivere un programma che accenda la lampada di una stanza soltanto se: (1) è notte e se (2) l’interruttore è acceso. Qui entra in gioco l’operatore AND: entrambe le condizioni devono essere vere affinché l’azione si verifichi. Allo stesso modo, potreste voler accendere la luce se è notte oppure se la stanza è buia. Questa volta è l’operatore OR a determinare l’esito dell’operazione. Infine, l’operatore NOT inverte il valore di verità: se non è giorno, allora deve essere notte.

Questi semplici esempi illustrano come operazioni booleane di base modellino il flusso di decisione nei programmi, permettendo ai computer di eseguire compiti che dipendono da semplici sì o no.

Variabili e tipi di dati

Le variabili sono i mattoni fondamentali di qualsiasi programma. Come il nome suggerisce, una variabile è un dato il cui valore può variare durante l’esecuzione di un programma. Ogni variabile ha un tipo, che determina la natura dei dati che può contenere e le operazioni che su di essa possono essere eseguite.

In linguaggi di programmazione come C, la dichiarazione di una variabile richiede di specificarne il tipo. Tra le variabili più semplici troviamo: intero (int), decimale (float, double), carattere (char), booleano (bool), etc. Questa tipizzazione aiuta a prevenire errori, come tentare di eseguire operazioni matematiche su stringhe di testo, e garantisce che il codice sia più comprensibile e sicuro.

In questo articolo vedremo solo alcuni tipi di variabili, ti invito dunque ad approfondire online le caratteristiche della programmazione in C. Scrivi tra i commenti se hai qualche perplessità o bisogno di chiarimenti.

Approfondimento

Consideriamo il seguente frammento di codice in C:

int numero = 10;
float decimale = 3.14;
char lettera = 'A';

Qui, abbiamo dichiarato tre variabili di tipi diversi, ognuna delle quali può essere utilizzata per scopi specifici nel nostro programma. La comprensione dei tipi di dati e delle variabili è cruciale per manipolare efficacemente i dati e realizzare algoritmi complessi.

Strutture di controllo

Faremo adesso una rapida panoramica delle strutture di controllo disponibili in C. Le strutture di controllo sono ciò che dà ai programmi la capacità di prendere decisioni e ripetere operazioni. Senza di esse, i nostri codici sarebbero semplici elenchi di istruzioni eseguite sequenzialmente, senza alcuna possibilità di adattarsi a condizioni diverse o di eseguire compiti ripetitivi senza duplicare il codice. Le strutture di controllo possono essere suddivise in strutture condizionali e strutture iterative.

Strutture condizionali

Le strutture condizionali, come if, else e switch, permettono di eseguire blocchi di codice solo se determinate condizioni sono soddisfatte. Ad esempio, un programma potrebbe verificare se l’input dell’utente è positivo prima di procedere con un calcolo:

if (input > 0) {
    printf("Il numero è positivo.\n");
} else {
    printf("Il numero non è positivo.\n");
}

Il costrutto if-else puo essere modellato a seconda delle esigenze infatti se ci serve valutare un’unica condizione basterà scrivere la nostra istruzione come:

if (condizione == 0) {
    // fai qualcosa
}

Se dobbiamo valutare una condizione alternativa nel caso in cui la prima dovesse fallire possiamo scrivere la nostra istruzione come:

if (condizione > 0) {
    // numero positivo
} else {
    // numero minore di zero o altro...
}

Se dobbiamo valutare più condizioni specifiche scriveremo:

if (condizione > 0) {
    // numero positivo
} else if(condizione == 0) {
    // numero uguale a zero
} else if(condizione < 0) {
    // numero minore di zero
} else {
    // condizione non prevista
}

Se le condizioni da valutare sono numerose conviene allora utilizzare il costrutto switch che può essere definito nel seguente modo:

switch(valore) {
    case 1:
        // fai qualcosa
        break;
    case 2:
        // fai qualcosa
        break;
    ...
    default:
        // fai qualcosa
}

In questo caso andremo a elencare tutti i casi (case) specifici che il nostro costrutto dovrà valutare, eventualmente possiamo aggiungere opzionalmente un caso di default che possa gestire qualunque condizione.

Strutture iterative

Un’altra tipologia di struttura di controllo sono le strutture iterative o cicliche, dove possiamo trovare i cicli: for, while e do-while. Le strutture iterative rendono possibile eseguire un blocco di codice più volte senza doverlo riscrivere. Questo è particolarmente utile per iterare su array o per eseguire un’azione finché una condizione non viene soddisfatta:

for(int i = 0; i < 10; i++) {
    printf("%d\n", i);
}

Questo frammento di codice sfrutta il costrutto for per stampare sul terminale i numeri da 0 a 9, dimostrando come il ciclo for possa semplificare operazioni contorte. Vediamo adesso un esempio che utilizzi il costrutto while.

while(condizione) {
    i++;
}

In questo frammento, ogni volta che la condizione sarà vera la variabile i verrà incrementata di un’unità. Vediamo adesso il costrutto do-while che a differenza del while effettua il controllo della condizione alla fine del ciclo.

do {
    i++;
} while(condizione)

In questo esempio, la prima operazione che viene effettuata è l’incremento della variabile i, successivamente viene verificata la condizione e, se vera viene ripetuto il codice a partire dal do; in caso contrario il ciclo viene chiuso.

Funzioni

Le funzioni sono blocchi di codice riutilizzabili progettati per eseguire una specifica attività. La capacità di raggruppare istruzioni in funzioni non solo rende il codice più organizzato e leggibile ma, permette anche di riutilizzare il codice stesso senza doverlo riscrivere ogni volta.

In C, una funzione è definita specificando un tipo di ritorno, un nome e, opzionalmente, un elenco di parametri. Ad esempio, la seguente funzione somma prende due numeri interi come input e restituisce tramite il comando return la loro somma:

int somma(int num1, int num2) {
    return num1 + num2;
}

In questo esempio somma è il nome della nostra funzione; il tipo di variabile definita prima del nome della funzione (int) è il tipo di dato che viene restituito, nel nostro caso un intero; i parametri tra parentesi (int num1, int num2) rappresentano i valori che daremo in input quando dichiareremo la nostra funzione.

Una funzione può ritornare un tipo di dato diverso dai valori in input

Approfondimento

Possiamo dunque invocare la nostra funzione nel seguente modo:

int x = 3;
int y = 2;
int z = somma(x, y);

Le funzioni possono essere chiamate da qualsiasi punto del programma, con o senza parametri, e possono restituire un valore. Questo meccanismo di “chiamata e ritorno” è fondamentale per strutturare programmi complessi in unità logiche e gestibili.

La funzione printf

La funzione printf è una funzione di output di formattazione in C che consente di stampare testo formattato sullo standard output (stdout), che corrisponde al terminale o alla console di output. È una delle funzioni standard disponibili nella libreria di C (stdio.h) ed è ampiamente utilizzata per visualizzare informazioni durante l’esecuzione di un programma. Vediamo dunque come è definita la funziona printf:

int printf(const char *format, ...);

Il primo argomento è una stringa così detta di formato che serve a specificare come i dati devono essere formattati e visualizzati. La stringa di formato può contenere caratteri di formattazione speciali, come “%d” per interi, “%f” per float, “%s” per stringhe, e così via. Gli argomenti successivi sono i valori da stampare e vengono sostituiti nei rispettivi segnaposto nella stringa di formato.

La funzione printf è ampiamente utilizzata per scopi di debug, output di informazioni di stato, visualizzazione di risultati e interazione con l’utente tramite la console. È uno strumento potente per la visualizzazione di dati in modo chiaro e leggibile durante lo sviluppo e la ritroveremo spesso negli esempi a seguire per stampare il valore delle variabili.

La struttura di un programma in C

In C un programma deve sempre possedere una e una sola funzione con un nome predefinito denominata main(). Questa funzione è la funzione principale lanciata al momento dell’esecuzione di un programma scritto in C

void main() {
    // il tuo codice qui
    return 0;
}

Anche la funzione main() può avere dei parametri in input e possono essere passati al programma eseguibile prima dell’avvio da linea di comando. La funzione main() con argomenti in input è definita nel seguente modo:

int main(int argc, char *argv[])

Il parametro intero argc rappresenta gli argomenti presenti nella riga di comando lanciata, incluso il nome del programma stesso, avremo dunque almeno un valore quando lanceremo il programma senza specificare parametri in ingresso. Il secondo parametro *argv[] serve a memorizzare gli argomenti della riga di comando.

Accesso alla memoria

Le informazioni che transitano nel computer vengono gestite da un’architettura modulare, dove ogni livello svolge specifiche azioni di elaborazione e trasmissione dei dati. Variabili, funzioni e regole di controllo di controllo sono tutti elementi salvati in memoria, per questo è fondamentale capire i processi interni che ne disciplinano il funzionamento.

In C, la memoria è organizzata in posizioni numerate chiamate “indirizzi di memoria”. Quando dichiariamo una variabile viene riservato uno spazio nella memoria per registrare e salvare il valore della variabile. Per accedere a questo valore è sufficiente definire all’interno del nostro codice il nome della variabile, mentre se volessimo conoscere l’indirizzo in cui è stata allocata la variabile basterà aggiungere il simbolo ‘&‘ prima della variabile. Vediamo qualche frammento di codice:

int valore = 5;
printf("%d", valore);  // output: "5" Lettura della variabile
printf("%d", &valore); // output: "2011167372" Lettura dell'indirizzo di memoria

Nel caso di semplici variabili possiamo in questo modo conoscere non soltanto il loro valore ma anche l’indirizzo di allocazione. Facciamo uno sforzo adesso e vediamo come poter sfruttare queste nozioni per utilizzare strutture dati più avanzate.

Array in C

In C come in altri linguaggi di programmazione, gli sviluppatori hanno la possibilità di gestire la memoria e l’accesso alle informazioni in essa contenute. Quando si progetta un software è importante stabilire se le informazioni che stiamo andando a gestire debbano essere organizzate o meno in strutture dati ben definite. La prime strutture dati che vedremo sono i vettori anche conosciuti come array.

Un vettore in C viene memorizzato in maniera sequenziale, le variabili cioè vengono memorizzate in posizioni di memoria contigue. Quando si accede a una variabile, il programma sa che la variabile successiva si trova nell’indirizzo di memoria a seguire. Questo rende gli array particolarmente efficienti per l’accesso agli elementi, dato che la posizione di ogni elemento può essere calcolata direttamente.

int numeri[5] = {1, 2, 3, 4, 5};

Tuttavia, gli array in C hanno una dimensione fissa, determinata al momento della dichiarazione. Questa staticità può essere limitante quando non si conosce a priori la quantità di dati da memorizzare o quando si necessita di una collezione dinamica che possa crescere nel tempo.

Puntatori in C

In C è possibile inoltre accedere direttamente a variabili o strutture dati allocati nella memoria, superando così i limiti dei dati sequenziali. I puntatori sono variabili speciali che contengono gli indirizzi di memoria di altre variabili. Vediamo un esempio di utilizzo dei puntatori in C:

int altezza = 10;
int *ptr; // Dichiarazione di un puntatore
ptr = &altezza; // Assegnazione dell'indirizzo di memoria di 'altezza' al puntatore
printf("%d", *ptr); // output: "10"

Sfruttando il carattere speciale ‘&‘ che abbiamo visto precedentemente, possiamo collegarci ad una variabile in maniera alternativa. Il puntatore, in questo esempio che stiamo osservando, è un collegamento alla variabile allocata, un alias della variabile puntata. Questo approccio può essere sfruttato in tanti modi per ottimizzare la memoria o ancora per creare strutture dati complesse.

Strutture (Struct) in C

Le struct in C sono utilizzate per raggruppare insieme variabili di tipi diversi sotto un unico nome, facilitando la gestione di dati complessi. Ad esempio, si può definire una struct per rappresentare un punto in uno spazio tridimensionale:

struct Punto {
    float x, y, z;
};

Le struct sono fondamentali per la creazione di strutture dati più complesse come ad esempio le liste collegate, le quali consentono di superare i limiti degli array grazie alla loro natura dinamica.

Buone pratiche di programmazione

Scrivere codice funzionale è solo una parte dell’equazione; scrivere codice chiaro, mantenibile ed efficiente è altrettanto importante. Adottare buone pratiche di programmazione non solo facilita la vita ai futuri sviluppatori che dovranno leggere e modificare il vostro codice ma aiutano, anche a distanza di tempo, a comprendere il codice creato e a ottimizzarlo.

Quando scrivi codice, è importante usare nomi che descrivano chiaramente lo scopo delle variabili, delle funzioni e delle classi. Evita soluzioni complicate e utilizza un approccio semplice che renda il codice più facile da testare, correggere e capire. Mantieni uno stile di scrittura uniforme in tutto il progetto, includendo la formattazione del codice, l’uso delle parentesi e la denominazione, per facilitare la manutenzione nel tempo.

Promuovi il riuso del codice creando funzioni e classi modulari e riutilizzabili, in modo da evitare la duplicazione e semplificare le modifiche. Commenta il codice per spiegare decisioni complesse e documenta i progetti in modo dettagliato per aiutare gli utenti e i collaboratori a comprenderli meglio.

Evita di ottimizzare il codice troppo presto; inizia con una scrittura chiara e corretta, e ottimizza solo dove necessario basandoti su misurazioni reali delle prestazioni. Considera attentamente l’uso delle risorse come memoria e CPU, poiché algoritmi e strutture dati efficienti possono fare la differenza in termini di prestazioni.

Ti piacerebbe programmare plugin audio?

Se sei interessato a questi ed altri argomenti non perdere l’occasione di partecipare on-line al corso base di “Sviluppo di Plugin Audio”. L’obbiettivo del corso è fornire ai partecipanti le competenze necessarie per creare software audio innovativi, aprendo nuove strade nel loro percorso professionale e creativo. In quanto corso base, al suo completamento gli allievi sono in grado di sviluppare alcune tra le tipologie essenziali di plugin audio come gain, delay ed equalizzatori.

Il corso prevede un approccio pratico e teorico finalizzato a  sviluppare una solida comprensione dei principi fondamentali dell’audio digitale, incoraggiando al contempo l’innovazione e la creatività nella creazione di nuovi strumenti e applicazioni audio.

Attraverso una piattaforma interattiva offerta da Absonant, gli studenti potranno non solo acquisire competenze tecniche in programmazione di plugin audio, ma anche interagire in tempo reale e partecipare a sessioni di laboratorio virtuali.

Corso online

Corso offerto da

logo absonant roma black

centro di formazione audiovisiva e multimediale di Roma

Chi è Nils Lewin

Mi chiamo Nicola Bombaci alias Nils Lewin, sono un ingegnere informatico con la passione per la musica e l’audio. Durante la mia crescita professionale ho deciso di fondere questi due mondi apparentemente diversi tra loro.

Articoli simili

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Prendi il controllo della tua musica

Inserisci la tua e-mail per ricevere la lista con risorse/strumenti per controllare i tuoi ascolti online.

HIMUSICIAN

Prendi il controllo
della tua musica

Una community di talenti emergenti, alla ricerca di risposte e nuovi collaboratori. Connettiti per migliorare e far crescere la tua musica.

Iscriviti alla newsletter e riceverai: