<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//IT"> <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <META NAME="GENERATOR" CONTENT="lfparser_2.25"> <META NAME="LFCATEGORY" CONTENT="SoftwareDevelopment"> <!-- this is used by a number of tools: =LF=AUTHOR: Lorne Bailey =LF=CAT___: SoftwareDevelopment =LF=TITLE_: GCC - la radice di tutto =LF=NUMBER: 229 =LF=ANAME_: article229.shtml --> <TITLE>lf229, SoftwareDevelopment: GCC - la radice di tutto</TITLE> <!-- stylesheet added by lfparser: --> <style type="text/css"> <!-- td.top {font-family: Arial,Geneva,Verdana,Helvetica,sans-serif; font-size:12 } pre { font-familiy:monospace,Courier } p.cl { color:#EE9500 } a.nodec { text-decoration:none } p.trans { font-size:8pt; text-align:right } p.clbox { width:50%; alignment:center; background-color:#FFD700; border-style:none; border-width:medium; border-color:#FFD700; padding:0.5cm ; text-align:center } p.code { width:80%; alignment:center; background-color:#aedbe8; border-style:none; border-width:medium; border-color:#aedbe8; padding:0.1cm ; text-align:left } p.foot { background-color:#AAAAAA; color:#FFFFFF; border-style:none; border-width:medium; border-color:#AAAAAA; padding:0.5cm ; margin-top:0.1cm; margin-right:1cm; margin-left:1cm; text-align:center } --> </style> </HEAD> <BODY bgcolor="#ffffff" text="#000000"> <!-- this is generated html code. NEVER use this file for your translation work. Instead get the file with the same article number and .meta.shtml in its name. Translate this meta file and then use lfparser program to generate the final article --> <!-- lfparser can be obtained from http://www.linuxfocus.org/~guido/dev/lfparser.html --> <!-- 2pdaIgnoreStart --> <!-- start navegation bar --> <!-- top navegation bar --> <TABLE summary="topbar_1" cellspacing="0" cellpadding="0" border="0" align="center" width="90%"> <TR bgcolor="#2e2292"> <TD class="top"><TABLE summary="topbar_1_logo" cellspacing="0" cellpadding="0" border="0" width= "100%"> <TR><TD width="319"><IMG src="../../common/images/logolftop_319x45.gif" alt="[LinuxFocus-icon]" width="319" height="45" align="left" border="0"></TD> <TD class="top"> <TABLE summary="topbar_1_links" width="100%"> <TR align="right"> <TD class="top"><A class="nodec" href="../index.shtml"><FONT color= "#DDDDDD" size="2">Home</FONT></A> | <A class= "nodec" href="../map.html"><FONT color= "#DDDDDD" size="2">Mappa</FONT></A> | <A class= "nodec" href="../indice.html"><FONT color= "#DDDDDD" size="2">Indice</FONT></A> | <A class="nodec" href="../Search/index.shtml"><FONT color= "#DDDDDD" size="2">Cerca</FONT></A> </TD> </TR> <TR align="right"> <TD class="top"> <HR width="100%" noshade size="1"> </TD> </TR> </TABLE> </TD> </TR> </TABLE> </TD> </TR> </TABLE> <!-- end top navegation bar --> <!-- blue bar --> <TABLE summary="topbar_2" cellspacing="0" cellpadding="0" border="0" align="center" width="90%"> <TR bgcolor="#00ffff"> <TD><IMG src="../../common/images/transpix.gif" width="1" height= "2" alt=""></TD> </TR> </TABLE> <!-- end blue bar --> <!-- bottom navegation bar --> <TABLE summary="topbar_3" cellspacing="0" cellpadding="0" border="0" align="center" width="94%"> <TR bgcolor="#000000"> <TD> <TABLE summary="topbar_3_links" cellspacing="0" cellpadding="1" border="0" width= "100%"> <TR align="center"> <TD WIDTH="20%"><A class="nodec" href="../News/index.shtml"><FONT color= "#FFFFFF">News</FONT></A> </TD> <TD WIDTH="5%"><FONT color="#FFFFFF">|</FONT> </TD> <TD WIDTH="20%"><A class="nodec" href="../Archives/index.html"><FONT color= "#FFFFFF">Archivo</FONT></A> </TD> <TD WIDTH="5%"><FONT color="#FFFFFF">|</FONT> </TD> <TD WIDTH="20%"><A class="nodec" href="../Links/index.html"><FONT color= "#FFFFFF">Link</FONT></A> </TD> <TD WIDTH="5%"><FONT color="#FFFFFF">|</FONT> </TD> <TD WIDTH="20%"><A class="nodec" href="../aboutus.html"><FONT color= "#FFFFFF">Cose LF</FONT></A> </TD> </TR> </TABLE> </TD> </TR> </TABLE> <!-- end bottom navegation bar --> <!-- stop navegation bar --> <!-- SSI_INFO --> <!-- tr_staticssi include virtual --> <!-- tr_staticssi exec cmd --> <!-- addedByLfdynahead ver 1.1 --><TABLE ALIGN="right" border=0><TR><TD ALIGN="right"><FONT SIZE="-1" FACE="Arial,Helvetica">Questo articolo è disponibile in: <A href="../../English/March2002/article229.shtml">English</a> <A href="../../Castellano/March2002/article229.shtml">Castellano</a> <A href="../../ChineseGB/March2002/article229.shtml">ChineseGB</a> <A href="../../Deutsch/March2002/article229.shtml">Deutsch</a> <A href="../../Francais/March2002/article229.shtml">Francais</a> <A href="../../Italiano/March2002/article229.shtml">Italiano</a> <A href="../../Portugues/March2002/article229.shtml">Portugues</a> <A href="../../Russian/March2002/article229.shtml">Russian</a> <A href="../../Turkce/March2002/article229.shtml">Turkce</a> <A href="../../Arabic/March2002/article229.shtml">Arabic</a> </FONT></TD></TR></TABLE><br> <!-- SSI_INFO STOP --> <!-- 2pdaIgnoreStop --> <!-- SHORT BIO ABOUT THE AUTHOR --> <TABLE ALIGN=LEFT BORDER=0 WIDTH="190" > <TR> <TD> <!-- 2pdaIgnoreStart --> <!-- PALM DOC --> <TABLE BORDER=0 hspace=4 vspace=4> <TR> <TD> <font size=1> <img src="../../common/images/2doc.gif" width=34 align=left border=0 height=22 alt="convert to palm"><a href="http://cgi.linuxfocus.org/cgi-bin/2ztxt">Convert to GutenPalm</a><br>or <a href="http://cgi.linuxfocus.org/cgi-bin/2pda">to PalmDoc</a></font> </TD> </TR> </TABLE> <!-- END PALM DOC --> <!-- 2pdaIgnoreStop --> <br> <img src="../../common/images/LorneBailey.gif" width="178" height="200" alt="[Lorne Bailey]"> <BR> Lorne Bailey <br> <small><sherm_pbody(at)yahoo.com></small> <BR><BR> <I>L'autore:</I><BR> <P> Lorne vive a Chicago a lavora come consulente informatico specializzato nel mettere e togliere dati in un database Oracle. Fin da quando è passato a programmare esclusivamente in ambiente *nix, Lorne ha completamente evitato l'"inferno DLL". Attualmente sta lavorando alla sua tesi in Scienze Informatiche. </P> <!-- TRANSLATED TO it --> <BR><BR><I>Tradotto in Italiano da:</I><BR> Alessandro Pellizzari <small><alex(at)neko.it></small> <br> <!-- TRANSLATED TO STOP --> <BR><i>Contenuto</i>: <UL> <LI><A HREF="#229lfindex0"> Le regole di GCC </A></LI> <LI><A HREF="#229lfindex1"> All'inizio... </A></LI> <LI><A HREF="#229lfindex2"> Pre-compilazione </A></LI> <LI><A HREF="#229lfindex3"> Compilazione </A></LI> <LI><A HREF="#229lfindex4"> Assembly </A></LI> <LI><A HREF="#229lfindex5"> Link </A></LI> <LI><A HREF="#229lfindex6"> Altre Due Opzioni Importanti </A></LI> <LI><A HREF="#229lfindex7"> Debugging </A></LI> <LI><A HREF="#229lfindex8"> Conclusioni </A></LI> <LI><A HREF="#229lfindex9"> Links </A></LI> <LI><A HREF="http://cgi.linuxfocus.org/cgi-bin/lftalkback?anum=229&lang=it">Discussioni su quest'articolo</A></LI> </UL> </TD></TR></TABLE> <!-- HEAD OF THE ARTICLE --> <br> <H2>GCC - la radice di tutto</H2> <IMG SRC="../../common/images/illustration229.gif" ALT="[Illustration]" HSPACE=10 width="200" height="60"> <!-- ABSTRACT OF THE ARTICLE --> <P><i>Premessa</i>: <P> Questo articolo presuppone che conosciate le basi del linguaggio C, e vi introdurrà all'uso di gcc come compilatore. Controlleremo che possiate richiamare il compilatore dalla linea di comando con un semplice sorgente in C. Quindi daremo una rapida occhiata a quello che succede e a come potete controllare la compilazione dei vostri programmi. Daremo anche un veloce sguardo all'uso di un debugger. </P> <HR size="2" noshade align="right"><BR> <!-- BODY OF THE ARTICLE --> <A NAME="229lfindex0"> </A> <H2> Le regole di GCC </H2> <p> Riuscite a immaginare di compilare software free con un compilatore proprietario e closed-source? Come sapreste cosa sta succedendo nel vostro eseguibile? Ci potrebbero essere tutti i tipi di backdoor o di trojan. Ken Thompson, in uno dei migliori hack di tutti i tempi, scrisse un compilatore che lasciava una backdoor nel programma 'login' e che replicava il trojan quando il compilatore si accorgeva di ricompilare se stesso. Leggete la descrizione di questo grande classico <a href="http://www.acm.org/classics/sep95">qui</a>. Fortunatamente abbiamo gcc. Ogni volta che fate <code> configure; make; make install </code> gcc fa un bel po' di sollevamento pesi dietro le quinte. Come possiamo fare in modo che gcc lavori per noi? Inizieremo scrivendo un gioco di carte, ma scriveremo solo quello che basta per dimostrare le possibilità del compilatore. Visto che stiamo iniziando da zero, c'è bisogno di capire il processo di compilazione per capire cosa deve essere fatto per creare un eseguibile e in che ordine. Daremo un'occhiata generale a come un programma in C viene compilato e alle opzioni che fanno fare al gcc quello che vogliamo che faccia. I passi (e i tool che li fanno) sono <a href="#precomp">Pre-compilazione</a> (gcc -E), <a href="#comp">Compilazione</a> (gcc), <a href="#assem">Assembly</a> (as), and <a href="#link">Link</a> (ld). </p> <A NAME="229lfindex1"> </A> <H2> All'inizio... </H2> <p> Prima di tutto dovremo sapere come richiamare il compilatore. In verità è semplice. Inizieremo col classico primo programma in C. (I veterani dovranno perdonarmi). </p> <p> <pre> #include <stdio.h> int main()<br/> { printf("Hello World!\n"); } </pre> </p> <p> salvate questo file come <code>game.c</code>. Potete compilarlo dalla linea di comando lanciando: <pre> gcc game.c </pre> Di default il compilatore C crea un eseguibile chiamato <code>a.out</code>. Potete lanciarlo scrivendo: <pre> a.out <b>Hello World</b> </pre> Ogni volta che compilate un programma, il nuovo <code>a.out</code> sovrascrive il precedente programma. Non sarete in grado di capire quale programma abbia generato l'attuale <code>a.out</code>. Possiamo risolvere questo problema dicendo al gcc che nome dare all'eseguibile con l'opzione <code>-o</code>. Chiameremo questo programma <code>game</code>, anche se potremmo nominarlo come vogliamo, visto che il C non ha le restrizioni di Java sui nomi. <pre> gcc -o game game.c </pre> <pre> game <b>Hello World</b> </pre> </p> <p> A questo punto siamo abbastanza lontani dall'avere un programma utils. Se pensate che ciò sia un male, dovreste considerare il fatto che abbiamo un programma che si compila e funziona. Man mano che aggiungeremo funzioni a questo programma vogliamo essere sicuri di mantenerlo funzionante. Sembra che ogni programmatore che inizia voglia scrivere 1.000 linee di codice e quindi correggerle tutte in una volta. Nessuno, e intendo nessuno, può fare una cosa del genere. Fate un programma che funziona, fate dei cambiamenti, lo fate funzionare ancora. Questo limita gli errori che dovrete correggere ogni volta. Inoltre saprete esattamente cosa avrete fatto che non funziona, quindi saprete dove concentrarvi. Questo vi evita di creare qualcosa che <b>voi</b> pensate deva funzionare, e magari si compila anche, ma non potrà mai diventare un eseguibile. Ricordate che il fatto che si compili non significa che funzioni bene. </p> <p> Il nostro prossimo passo è di creare un file header per il nostro gioco. Un file header concentra le dichiarazioni di funzioni e tipi di dati in un solo posto. Questo garantisce che le strutture dati siano definite in modo consistente in modo che ogni parte del nostro programma veda ogni cosa esattamente allo stesso modo. </p> <pre> #ifndef DECK_H #define DECK_H #define DECKSIZE 52 typedef struct deck_t { int card[DECKSIZE]; /* numero di carte usate */ int dealt; }deck_t; #endif /* DECK_H */ </pre> <p> Salvate questo file come <code>deck.h</code>. Solo i file con estensione <code>.c</code> vengono compilati, quindi dovremo cambiare il nostro game.c Alla linea 2 di game.c scrivete <code>#include "deck.h"</code>. Alla linea 5 scrivete <code>deck_t deck;</code> Per avere la certezza di non aver introdotto errori, compilatelo di nuovo. <pre> gcc -o game game.c </pre> </p> <p> Nessun errore, nessun problema. Se non riuscite a compilarlo lavorateci finché non ci riuscirete. </p> <A NAME="229lfindex2"> </A> <H2> <a name="precomp"> Pre-compilazione</a> </H2> <p> Come fa il compilatore a sapere che tipo è <code>deck_t</code>? Lo sa perché durante la pre-compilazione copia il file "deck.h" dentro il file "deck.c". Le direttive del pre-compilatore nel codice sorgente iniziano con "#". Potete richiamare il pre-compilatore tramite il front-end di gcc con l'opzione <code>-E</code>. <pre> gcc -E -o game_precompile.txt game.c wc -l game_precompile.txt 3199 game_precompile.txt </pre> Quasi 3.200 linee di output! La maggior parte di queste vengono dall'include <code>stdio.h</code> ma se ci guardate dentro ci trovere anche le nostre dichiarazioni. Se non passate un nome di file con l'opzione <code>-o</code> l'output verrà mandato in console. Il processo di pre-compilazione dà maggior flessibilità al codice eseguendo tre compiti principali. <ol> <li>Copia i file "#include" nel sorgente che deve essere compilato.</li> <li>Sistituisce i testi "#define" con il loro valore.</li> <li>Sostituisce le macro col loro codice quando vengono chiamate.</li> </ol> Questo consente di avere costanti con un nome (per esempio DECKSIZE rappresenta il numero di carte in un mazzo) usate in tutto il sorgente, definite in un solo posto e aggiornate automaticamente dappertutto non appena il valore cambia. Normalmente non userete mai l'opzione <code>-E</code> da sola, ma lascerete che passi il suo output al compilatore. </p> <A NAME="229lfindex3"> </A> <H2> <a name="comp">Compilazione</a> </H2> <p> Come passo intermedio, gcc trasforma il vostro codice in Assembly. Per farlo deve capire cosa intendevate fare analizzando il vostro codice. Se avete commesso degli errori di sintassi ve lo dirà e la compilazione fallirà. Di solito la gente confonde questo passo con l'intero processo di compilazione. Ma c'è ancora molto lavoro da fare per gcc. </p> <A NAME="229lfindex4"> </A> <H2> <a name="assem">Assembly</a> </H2> <p> <code>as</code> trasforma il codice Assembly in codice oggetto. Il codice oggetto non può ancora essere lanciato sulla CPU, ma ci si avvicina molto. L'opzione <code>-c</code> trasforma un file .c in un file oggetto con estensione .o Se lanciamo <pre> gcc -c game.c </pre> creiamo automaticamente un file che si chiama game.o Qui siamo incappati in un punto importante. Possiamo prendere un qualsiasi file .c e creare un file oggetto da esso. Come vedremo più avanti potremo combinare questi file oggetto in un eseguibile nella fase di Link. Andiamo avanti col nostro esempio. Poiché stiamo programmando un gioco di carte abbiamo definito un mazzo di carte come un <code>deck_t</code>, creeremo una funziona per mischiare il mazzo. Questa funzione prenderà un puntatore a un tipo deck e lo riempie con delle carte messe a caso. Tiene traccia di quali carte sono già state aggiunte con l'array 'drawn'. Questo arraydi DECKSIZE elementi ci impedisce di duplicare un valore di carta. </p> <pre> #include <stdlib.h> #include <stdio.h> #include <time.h> #include "deck.h" static time_t seed = 0; void shuffle(deck_t *pdeck) { /* Tiene traccia di che numeri sono stati usati */ int drawn[DECKSIZE] = {0}; int i; /* Inizializzazione da fare una volta di rand */ if(0 == seed) { seed = time(NULL); srand(seed); } for(i = 0; i < DECKSIZE; i++) { int value = -1; do { value = rand() % DECKSIZE; } while(drawn[value] != 0); /* segna il valore come usato */ drawn[value] = 1; /* codice di debug */ printf("%i\n", value); pdeck->card[i] = value; } pdeck->dealt = 0; return; } </pre> <p> Salvate questo file come <code>shuffle.c</code>. Abbiamo inserito del codice di debug in questo codice in modo che, quando viene lanciato, scriva i valori delle carte che genera. Questo non aggiunge niente alle funzionalità del programma, ma è cruciale adesso che non possiamo vedere cosa succede. Visto che stiamo appena cominciando il nostro gioco non abbiamo altro modo di sapere se la nostra funzione fa quello che vogliamo. Con il comando printf potete vedere esattamente cosa sta succedendo in modo che quando passeremo alla prossima fase sapremo che il mazzo viene mescolato bene. Dopo che saremmo soddisfatti del buon funzionamento potremo togliere la linea dal nostro codice. Questa tecnica di debugging può sembrare spartana, ma fa quello che deve fare con il minimo sforzo. Discuteremo di debugger più sofisticati in seguito. </p> Notate due cose. <ol> <li> Passiamo il parametro per indirizzo, e lo si capisce dall'operatore '&' (indirizzo di). Questo passa l'indirizzo in memoria della variabile alla funzione, in modo che la funzione possa cambiare la variabile stessa. È possibile programmare con variabili globali, ma dovrebbero essere usate molto raramente. I puntatori sono una parte importante del C e dovreste imparare a usarli molto bene. </li> <li> Stiamo usando una chiamata a funzione da un nuovo file .c. Il Sistema Operativo cerca sempre una funzione di nome 'main' e inizia l'esecuzione da lí. <code>shuffle.c</code> non ha una funzione 'main' e quindi non può essere trasformato in un eseguibile indipendente. Dobbiamo attaccarlo ad un altro programma che abbia una 'main' e che chiami la funzione 'shuffle'. </li> </ol> <p> Lanciate il comando <pre> gcc -c shuffle.c </pre> e accertatevi che crei un nuovo file chiamato <code>shuffle.o</code>. Editate il file game.c e, alla linea 7, dopo la dichiarazione della variabile <code>deck</code> di tipo deck_t, aggiungete la linea <pre> shuffle(&deck); </pre> Ora, se tenteremo di creare un eseguibile allo stesso modo di prima otterremo un errore <pre> gcc -o game game.c /tmp/ccmiHnJX.o: In function `main': /tmp/ccmiHnJX.o(.text+0xf): undefined reference to `shuffle' collect2: ld returned 1 exit status </pre> La compilazione è andata a buon fine perché la sintassi era corretta. La fase di link è fallita perché non abbimo detto al compilatore dove fosse la funzione 'shuffle'. Cos'è la fase di <i>link</i> e come diciamo al compilatore dove trovare questa funzione? </p> <A NAME="229lfindex5"> </A> <H2> <a name="link">Link</a> </H2> <p> Il linker, <code>ld</code>, prende il codice oggetto precedentemente creato da <code>as</code> e lo trasforma in un eseguibile col comando <pre> gcc -o game game.o shuffle.o </pre> Questo unisce i due codici oggetto insieme e crea l'eeguibile <code>game</code>. </p> <p> Il linker trova la funzione <code>shuffle</code> nell'oggetto shuffle.o e la include nell'eseguibile. La cosa veramente interessante dei file oggetto è il fatto che se volessimo usare di nuovo quella funzione, tutto ciò che dovremmo fare sarebbe includere il file "deck.h" e unire il file oggetto <code>shuffle.o</code> nel nuovo file eseguibile. </p> <p> Il riutilizzo di codice, come in questo caso, viene fatto spesso. Non abbiamo scritto la funzione <code>printf</code> che abbiamo chiamato prima come funzione di debug, il linker ha trovato la sua definizione nel file che abbiamo incluso con <code>#include <stdlib.h></code> e l'ha unita al codice oggetto contenuto nella libreria C (/lib/libc.so.6). In questo modo possiamo usare le funzioni di qualcun'altro, sapendo che funzionano, e preoccuparci solo di risolvere i nostri problemi. Questo è il motivo per cui i file header solitamente contengono solo le definizioni delle funzioni e non il codice vero e proprio. Normalmente si creano file oggetto o librerie che il linker metterà nell'eseguibile. Un problema potrebbe sorgere con il nostro codice poiché non abbiamo messo nessuna definizione di funzione nel nostro header. Cosa possiamo fare per essere sicuri che tutto funzioni bene? </p> <A NAME="229lfindex6"> </A> <H2> <a name="lasttwo">Altre Due Opzioni Importanti</a> </H2> <p> L'opzione <code>-Wall</code> abilita tutti i tipi di avvertimenti sulla sintassi del linguaggio per essere sicuri che il nostro codice sia corretto e il più portabile possibile. Quando usiamo questa opzione e compiliamo il nostro codice vediamo qualcosa come: <pre> game.c:9: warning: implicit declaration of function `shuffle' </pre> Questo ci permette di sapere che abbiamo ancora un po' di lavoro da fare. Dobbiamo aggiungere una linea al nostro header dove diamo al compilatore tutte le informazionisulla nostra funzione <code>shuffle</code> in modo che possa fare tutti i controlli di cui ha bisogno. Sembra una difficoltà inutile, ma separa la definizione dall'implementazione e ci permette di usare la nostra funzione dove vogliamo semplicemente includendo il nostro nuovo header nel codice oggetto. Metteremo questa riga nel file deck.h <pre> void shuffle(deck_t *pdeck); </pre> Questo ci libererà del messaggio di avvertimento. </p> <p> Un'altra opzione comune del compilatore è l'ottimizzazione <code>-O#</code> (per esempio -O2). Questo dice al compilatore il livello di ottimizzazione che vogliamo. Il compilatore conosce un sacco di trucchi per far andare più veloce il nostro codice. Per un programma piccolo come il nostro non noterete alcuna differenza, ma per programmi più grandi potreste ottenere buoni aumenti di velocità. Lo vedete dappertutto, quindi dovreste sapere cosa significa. </p> <A NAME="229lfindex7"> </A> <H2> <a name="debug">Debugging</a> </H2> <p> Come sappiamo tutti, il fatto che il codice venga compilato non significa che funzioni nel modo che vogliamo. Potete verificare che tutti i numeri vengano usati una sola volta lanciando <pre> game | sort - n | less </pre> e controllando che non ne manchino. Cosa facciamo se c'è un problema? Come troviamo l'errore? </p> Potete controllare il codice con un debugger. La maggior parte delle distribuzioni rendono disponibile il classico gdb. Se la linea di comando vi spaventa come lo fa a me, KDE offre una buona interfaccia con <a href="http://members.nextra.at/johsixt/kdbg.html">KDbg</a>. Ci sono anche altre interfacce, e sono molto simili. Per iniziare il debugging, scegliete File->Executable e trovate il vostro programma <code>game</code>. Quando premete F5 o selezionate Execution->Run dal menu dovreste vedere l'output su un'altra finestra. Cosa succede? Non vediamo niente nella finestra. Non preoccupatevi, non è KDbg che non funziona. Il problema nasce dal fatto che non abbiamo messo informazioni di debug nel nostro codice eseguibile, quindi Kdbg non può dirci cosa sta succedendo internamente. L'opzione del compilatore <code>-g</code> inserisce le informazioni richieste nei file oggetto. Dovete compilare i file oggetto (estensione .o) con questa opzione, quindi il comando diventa <pre> gcc -g -c shuffle.c game.c gcc -g -o game game.o shuffle.o </pre> Questo inserisce degli agganci nell'eseguibile per permettere a gdb e KDbg di capire cosa sta succedendo. Il debugging è un'abilità importante, vale il tempo che dedicherete a imparare a usarla bene. Il modo in cui i debugger aiutano i programmatori è la loro capacità di mettere dei 'Breakpoint' nel codice sorgente. Provate a inserirne uno facendo click col tasto destro sulla linea che chiama la funzione <code>shuffle</code>. Un piccolo cerchio rosso dovrebbe apparire vicino alla riga. Ora, quando premete F5 il programma ferma la sua esecuzione a quella linea. Premete F8 per entrare <i>dentro</i> la funzione shuffle. Hey, ora state guardando il codice dentro <code>shuffle.c</code>! Possiamo controllare l'esecuzione passo per passo e vedere cosa sta realmente accadendo. Se passate il puntatore su una variabile locale potete vedere cosa contiene. Carino. Molto meglio di quelle istruzioni <code>printf</code>, no? </p> <A NAME="229lfindex8"> </A> <H2> Conclusioni </H2> <p> Questo articolo si è presentato come un rapido giro sulla compilazione e il debugging di programmi C. Abbiamo parlato dei passi che un compilatore deve compiere e di quali opzioni passare a gcc per fargli fare tali passi. Abbiamo accennato al linking di librerie condivise e abbiamo terminato con una introduzione ai debugger. Serve ancora un sacco di lavoro per sapere esattamente cosa state facendo, ma spero che questo articolo vi sia servito per iniziare col piede giusto. Potete trovare ulteriori informazioni nelle pagine <code>man</code> e <code>info</code> di <code>gcc</code>, <code>as</code> e <code>ld</code>. </p> <p> Scrivere codice da soli è la cosa migliore per imparare. Per fare pratica, potreste prendere i frammenti di codice del gioco di carte di questo articolo e scrivere un gioco di blackjack. Prendetevi il tempo di imparare come funziona un debugger. È molto più semplice partire con una interfaccia grafica come KDbg. Se aggiungerete poche funzionalità alla volta ne verrete fuori prima di quanto pensiate. Ricordate di mantenerlo funzionante! <p> Queste sono alcune delle cose di cui avrete bisogno per fare un gioco completo. <ul> <li> Una definizione di un giocatore (per esempio, potreste definire deck_t come player_t).</li> <li> Una funzione che dia un certo numero di carte a un giocatore. Ricordate di incrementare il numero di carte date nel mazzo per tenere traccia di dove prendere la prossima carta da dare. Ricordate di terere traccia di quante carte ci sono in mano al giocatore. </li> <li> Un qualche tipo di interazione per chiedere al giocatore se vuole un'altra carta.</li> <li> Una funzione che stampi le carte del giocatore. La <i>carta</i> è valore%13 (valori da 0 a 12), il <i>seme</i> è valore/13 (valori da 0 a 3) </li> <li> Una funzione per determinare il valore della mano del giocatore. L'asso è la carta con numero 0 e può valere 1 o 11. I re hanno il numero 12 e valgono 10 </li> </ul> </p> </p> <A NAME="229lfindex9"> </A> <H2> <a name="links">Links</a> </H2> <ul> <li><a href="http://www.gnu.org/directory/gcc.html">gcc</a> GCC GNU Compiler Collection</li> <li><a href="http://www.gnu.org/directory/gdb.html">gdb</a> GNU Debugger </li> <li><a href="http://members.nextra.at/johsixt/kdbg.html">KDbg</a> KDE's GUI Debugger </li> <li> <a href="http://www.acm.org/classics/sep95">Award Winning Compiler Hack</a> Ken Thompson's great compiler hack </li> </ul> <!-- vim: set sw=2 ts=2 et tw=74: --> <!-- 2pdaIgnoreStart --> <A NAME="talkback"> </a> <h2>Discussioni su quest'articolo</h2> ogni articolo possiede una sua pagina di discussione, da questa pagina puoi inviare un commento o leggere quelli degli altri lettori: <center> <table border="0" CELLSPACING="2" CELLPADDING="1"> <tr BGCOLOR="#C2C2C2"><td align=center> <table border="3" CELLSPACING="2" CELLPADDING="1"> <tr BGCOLOR="#C2C2C2"><td align=center> <A href="http://cgi.linuxfocus.org/cgi-bin/lftalkback?anum=229&lang=it"><b> pagina di discussione </b></a> </td></tr></table> </td></tr></table> </center> <HR size="2" noshade> <!-- ARTICLE FOOT --> <CENTER><TABLE WIDTH="98%"> <TR><TD ALIGN=CENTER BGCOLOR="#9999AA" WIDTH="50%"> <A HREF="../../common/lfteam.html">Webpages maintained by the LinuxFocus Editor team</A> <BR><FONT COLOR="#FFFFFF">© Lorne Bailey, <a href="../../common/copy.html">FDL</a> <BR><a href="http://www.linuxfocus.org">LinuxFocus.org</a></FONT> <BR><a href="http://cgi.linuxfocus.org/cgi-bin/lfcomment?lang=it&article=article229.shtml" target="_TOP">Click here to report a fault or send a comment to LinuxFocus</A><BR></TD> <TD BGCOLOR="#9999AA"> <!-- TRANSLATION INFO --> <font size=2>Translation information:</font> <TABLE> <tr><td><font size="2">en --> -- : Lorne Bailey <small><sherm_pbody(at)yahoo.com></small></font></td></tr> <tr><td><font size="2">en --> it: Alessandro Pellizzari <alex(at)neko.it></font></td></tr> </TABLE> </TD> </TR></TABLE></CENTER> <p><font size=1>2002-02-28, generated by lfparser version 2.25</font></p> <!-- 2pdaIgnoreStop --> </BODY> </HTML>