Come strutturare le funzioni C in una libreria di utilità riutilizzabile

14

Hai scritto del codice. Funziona. Ma ora vuoi usare il generatore rand() o la routine bubble_sort in un progetto completamente diverso. Il copia-incolla è pigro. È anche fragile. Quando aggiorni una versione, devi scovare ogni copia del codice.

Il trasloco professionale? Costruisci una biblioteca.

Nell’ecosistema C, una libreria non è una magica scatola nera. Sono solo due file che indossano cappelli diversi. Hai bisogno di un file di intestazione (.h ) e di un file sorgente (.c ). L’intestazione dice al resto del mondo quali funzioni esistono. Il file sorgente effettivamente fa il lavoro.

Costruire l’interfaccia: util.h

Il file di intestazione funge da contratto. Non contiene la logica. Contiene le promesse. Costanti, tipi e prototipi di funzioni.

Creare un file denominato util.h.

Quelle parole chiave “extern” stanno facendo un lavoro pesante. Dicono al compilatore: “Non cercare l’implementazione qui. La troverò più tardi durante il collegamento”. Se sei bloccato su un compilatore legacy che precede i moderni standard C, rimuovi i parametri da “bubble_sort”. I vecchi compilatori sono schizzinosi in questo modo.

Nascondere il macchinario: util.c

Ora passiamo al codice vero e proprio. Salvalo come util.c.

Notare la direttiva include. Utilizziamo le virgolette ("util.h" ) invece delle parentesi angolari ( ). La differenza conta. Le virgolette vengono visualizzate nella directory corrente. Le parentesi angolari guardano nelle directory di sistema. Questo file è locale. Appartiene qui.

Ecco la parte sottile: rand_seed. Si trova in “util.c”. Non è in util.h. Queste sono informazioni nascoste in azione. Il codice che utilizza questa libreria può chiamare rand(), ma non può toccare direttamente il seed. Lo Stato è incapsulato. Per un’applicazione rigorosa, potresti inserire la parola chiave “static” davanti alla definizione della variabile. Questo lo blocca saldamente. Nessun accesso esterno. Periodo.

Utilizzo della libreria: main.c

Ora scrivi il programma che lo utilizza. Salvalo come main.c.

Più corto? SÌ. Più pulito? Assolutamente. Al programma principale non interessa il modo in cui rand() genera i numeri. Richiede solo un numero. Questa separazione è il punto centrale.

Compilazione e collegamento

Come si trasformano questi file separati in un eseguibile in esecuzione? Segui la danza in tre passi.

Innanzitutto, compila il sorgente della libreria in un file oggetto. Supponendo che tu stia su un sistema simile a UNIX utilizzando GCC:

“bash.”
gcc -c -g util.c

Questo genera main.o. Ancora una volta, solo codice macchina. Ancora bloccato senza la logica della biblioteca.

Infine, collegali insieme.

“bash.”
gcc -o main main.o util.o
“`

Questo comando prende entrambi i file oggetto e li unisce in un unico eseguibile chiamato “main”. Ora hai un programma completo. Eseguilo con ./main (o semplicemente main se sei su Windows o ce l’hai nel tuo percorso).

Sono molti i passaggi per due funzioni. Ma immagina di farlo per un progetto con cinquanta file. Compila ogni file .c una volta. Li colleghi insieme. Cambiare una funzione nella libreria? Ricompilare solo quel file. Ricollegare. Il resto resta intatto.

I makefile lo automatizzano