31.05.2013 Views

Tricky C - Si® @lbert Site

Tricky C - Si® @lbert Site

Tricky C - Si® @lbert Site

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

26 - <strong>Tricky</strong> C<br />

string non contiene la parola "Ciao", ma i 16 bit che esprimono la parte offset del suo indirizzo. A<br />

sua volta, "Ciao" occupa 5 byte di memoria. Proprio 5, non si tratta di un errore di stampa: i 4 byte<br />

necessari a memorizzare i 4 caratteri che compongono la parola, più un byte, nel quale il compilatore<br />

memorizza il valore binario 0, detto terminatore di stringa o null terminator. In C, tutte le stringhe sono<br />

chiuse da un null terminator, ed occupano perciò un byte in più del numero di caratteri "stampabili" che le<br />

compongono.<br />

La prima chiamata a printf() passa quale argomento proprio string: dunque la stringa<br />

parametro indispensabile di printf() non deve essere necessariamente una stringa di formato quando<br />

l'unica cosa da visualizzare sia proprio una stringa. Lo è, però, quando devono essere visualizzati caratteri<br />

o numeri, o stringhe formattate in un modo particolare, come avviene nella seconda chiamata.<br />

Qui va sottolineato che per visualizzare una stringa con printf() occore fornirne l'indirizzo,<br />

che nel nostro caso è il contenuto del puntatore string. Se string punta alla stringa "Ciao", che<br />

cosa restituisce l'espressione *string? La tentazione di rispondere "Ciao" è forte, ma se così fosse<br />

perché per visualizzare la parola occorre passare a printf() string e non *string? Il problema<br />

non si poneva con gli esempi precedenti, perché tutti i puntatori esaminati indirizzavano un unico dato di<br />

un certo tipo. Con le dichiarazioni<br />

float numero = 12.5;<br />

float *numPtr = &numero;<br />

si definisce il puntatore numPtr e lo si inizializza in modo che contenga l'indirizzo della variabile<br />

numero, la quale, in fondo proprio come string, occupa più di un byte. In questo caso, però, i 4 byte<br />

di numero contengono un dato unitariamente considerato. In altre parole, nessuno dei 4 byte che la<br />

compongono ha significato in sé e per sé. Con riferimento a string, al contrario, ogni byte è un dato a<br />

sé stante, cioè un dato di tipo char: bisogna allora precisare che un puntatore indirizza sempre il primo<br />

byte di tutti quelli che compongono il tipo di dato considerato, se questi sono più d'uno. Se ne ricava che<br />

string contiene, in realtà, l'indirizzo del primo carattere di "Ciao", cioè la 'C'. Allora *string<br />

non può che restituire proprio quella, come si può facilmente verificare con la seguente chiamata a<br />

printf():<br />

printf("%c è il primo carattere...\n",*string);<br />

Non dimentichiamo che le stringhe sono, per il compilatore C, semplici sequenze di char: la<br />

stringa del nostro esempio inizia con il char che si trova all'indirizzo contenuto in string (la 'C') e<br />

termina con il primo byte nullo incontrato ad un indirizzo uguale o superiore a quello (in questo caso il<br />

byte che segue immediatamente la 'o').<br />

Per accedere ai caratteri che seguono il primo è sufficiente incrementare il puntatore o,<br />

comunque, sommare ad esso una opportuna quantità (che rappresenta l'offset, cioè lo spostamento,<br />

dall'inizo della stringa stessa). Vediamo, come al solito, un esempio:<br />

int i = 0;<br />

while(*(string+i) != 0) {<br />

printf("%c\n",*(string+i));<br />

++i;<br />

}<br />

L'esempio si basa sull'aritmetica dei puntatori (pag. 33), cioè sulla possibilità di accedere ai dati<br />

memorizzati ad un certo offset rispetto ad un indirizzo sommandovi algebricamente numeri interi. Il ciclo<br />

visualizza la stringa "Ciao" in senso verticale. Infatti l'istruzione while (finalmente una "vera"<br />

istruzione C!) esegue le istruzioni comprese tra le parentesi graffe finché la condizione espressa tra le<br />

parentesi tonde è vera (se questa è falsa la prima volta, il ciclo non viene mai eseguito; vedere pag. 79): in<br />

questo caso la printf() è eseguita finché il byte che si trova all'indirizzo contenuto in string

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!