• Non ci sono risultati.

Passare parametri al main

Nel documento Imparare il C una guida per Linux (pagine 54-64)

Tipi di dati complessi

4.1.1 Passare parametri al main

4.1.1 Passare parametri al main

Il listato seguente mostra un’ altra importante caratteristica standard del C che `e il passaggio di parametri al main dalla riga di comando.

#include <stdio.h>

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

printf ("%s", argv[1] ); }

Dove argc e’ per default il numero di argomenti passati a riga di comando, argv[]

e’ un vettore che contiene il valore di questi ultimi. Bisogna pero’ dichiarare la funzione main() come si vede sopra, ove si intenda recuperare il valore degli argomenti passati dalla riga di comando.

32 CAPITOLO 4. TIPI DI DATI COMPLESSI $ ./argomenti barbablu

non fa niente altro che stampare il valore di argv[1]

ovvero: barbablu

N.B.: argv[0]

e’, di default, il nome del programma stesso.

4.2 Strutture e unioni

Una struttura `e un tipo di dato definibile dall’utente, e rappresenta un insieme di campi costituiti da tipi-base, a differenza dell’array, di tipo differente tra di loro; ad esempio: struct indirizzo{ char citta[128]; char via[128]; int civico[5]; } `

e la dichiarazione di una struttura contenenti i campi citta, via, civico del tipo sopra indicato. Agli elementi della struttura si accede mediante l’operatore . (punto).

Ad esempio, definita una variabile indirizzo var_indirizzo;

Si assegnano dei valori nella maniera che segue: var_indirizzo.citta = "stringa citt`a"; var_indirizzo.via = "stringa via"; var_indirizzo.civico = 57;

Leggermente diversa `e l’utilit`a delle union, anche se il loro utilizzo `e pressoch`e analogo a quello di una struct. Es.:

4.3 Una utile estensione delle struct: I campi di bit Imparare il C pag. 33

union miaunione{ int numero;

float piu_grande; }

Fa s`ı che venga allocato lo spazio per la pi`u grande delle variabili, poich`e queste si trovano a condividere il medesimo spazio in memoria. L’impiego di union `e utile principalmente per rendere portabili alcuni tipi di dati sotto piattaforme differenti.

4.3 Una utile estensione delle struct: I campi

di bit

Come detto, esiste un altro tipo di dato aggregato, molto utile per la gestione a basso livello della memoria, il bitfield. L’ impiego di campi di bit si rende necessario quando si voglia accedere ai singoli bit. In generale, un bitfield `e definito in maniera analoga a quanto segue:

struct nome_struttura{

type nome_var1 : dimensione1; type nome_var2 : dimensione2; type nome_var3 : dimensione3; }

struct_nomestruttura mia_var;

Dove type realizza il tipo del campo di bit: Si possono avere:

int, unsigned, signed

Ovviamente, ove si necessiti di un singolo bit, si scriver`a unsigned.

Inoltre, la dimensione indicata deve corrispondere al numero di bit singoli che il campo comprende.

34 CAPITOLO 4. TIPI DI DATI COMPLESSI L’accesso e le istruzioni di assegnazione di un valore ai membri di una variabile di tale tipo, avvengono in maniera esattamente analoga alle comuni strutture. es.: struct byte_acchiappato_dalla_seriale{ unsigned primo: 1; unsigned secondo: 1; unsigned terzo: 1; unsigned quarto: 1; unsigned quinto: 1; unsigned sesto: 1; unsigned settimo: 1; unsigned ultimo: 1; }arrivato;

Volendo interpretare i bit della struttura sopra come valori boleani, si potrebbe voler fare un controllo del tipo:

if (arrivato.primo) printf("\t Ma chi te lo ha fatto fare\n"); Ovvero, voler fare un semplice assegnamento del tipo:

arrivato.primo = 0; arrivato.ultimo = 1;

Se qualcuno volesse sapere quale sia il piazzamento ottenuto, basterebbe verificare quale sia il bit settato ad uno (ovvero: qule campo restituisce il valore VERO).

In maniera abbastanza palese, l’esempio sopra non `e economico come sem-bra a prima vista, tuttavia serve a mostrarere l’impiego pratico dei campi di bit. L’utilit`a vera `e nella possibilit`a di impiegare, ove sia possibile, il quanto minimo di informazione, laddove un intero byte rappresenterebbe uno spreco inutile di risorse cruciali. Il caso tipico `e rappresentato dalla scrittura di un kernel, dove `e inoltre necessario controllare i singoli registri della CPU. Il C non sarebbe il linguaggio potente e versatile che di fatto `e, se non avesse que-sta importante caratteristica, che permette di evitare l’impiego del linguaggio assembly laddove con altri linguaggi non sarebbe possibile.

4.3 Una utile estensione delle struct: I campi di bit Imparare il C pag. 35

4.3.1 La keywordtypedef

Quando si voglia definire un nuovo tipo, si pu`o usare la dichiarazione typedef Ad esempio, si pu`o fare:

typedef struct indirizzo{

char citta[128]; char via[128]; int civico[5]; } E poi dichiarare: indirizzo mio_indirizzo;

Capitolo 5

I puntatori

5.1 Alcune considerazioni

Un puntatore ´e una variabile che contiene un indirizzo di memoria. L’im-piego dei puntatori `e una delle caratteristiche per cos`ı dire triviali del C. Comprendere bene l’uso dei puntatori `e assolutamente necessario, anche per scrivere programmi semplici e che, scritti in linguaggi pi`u amichevoli, appa-iono formalmente non farne uso. Questo in quanto il C non tenta in alcun modo di nascondere l’uso a basso livello della memoria; ci`o ha il risultato di rendere la vita pi`u difficile al programmatore, ma lo rende anche pi`u libero, e necessariamente consapevole di quello che sta facendo.

5.2 Dichiarazione di un puntatore

Ogni puntatore contiene la locazione di memoria di un oggetto di un cer-to tipo; per quescer-to, esiscer-tono diversi tipi di puntacer-tori; un puntacer-tore viene dichiarato nella maniera seguente:

int *punt_int; /* Puntatore ad intero */

double *punt_double; /* Puntatore a double */ char *punt_char; /* Puntatore a carattere */

...eccetera.

5.3 Operatori sui puntatori

Sono definiti tre diversi operatori per le operazioni con puntatori: L’operatore

38 CAPITOLO 5. I PUNTATORI &

Ha l’impiego seguente: #include<stdio.h>

int main(int argc , char *argv[]) { int *miopunt_intero; int mioint = 7; miopunt_intero = &mioint; printf("%x", &miopunt_intero ); }/* main */

Questo breve programma stampa, sul mio sistema: bffff974 Ovvero, l’in-dirizzo di memoria in cui `e conservata la variabile

mioint.

L’operatore di dereferenziazione *

5.3 Operatori sui puntatori Imparare il C pag. 39 1 #include<stdio.h>

2

3 int main(int argc , char *argv[]) 4 {

5

6 int *miopunt_intero; 7 int mioint = 7;

8 miopunt_intero = & mioint; 9

10 printf("%x", &miopunt_intero ); 11 }

Il codice sopra stampa: 7

Il terzo operatore (operatore freccia) ->

´e utile per fare riferimento agli elementi di una struct puntata; per es., se si ´e definita la struct: struct indirizzo{ char citta[128]; char via[128]; int civico[5]; }

struct indirizzo mioind; ed un puntatore alla struct:

struct indirizzo *punt; punt = & mioind;

si pu`o accedere agli elementi della struct facendo: mia_citta = punt-> citta;

mia_via = punt-> via; mia_citta = punt-> civico;

Si noti che l’operatore -> equivale alla dereferenziazione del puntatore a struct, pi`u il passaggio all’elemento; ovvero:

40 CAPITOLO 5. I PUNTATORI equivale a:

punt -> citta;

L’operatore -> viene spesso utilizzato nelle linked lists per accedere, come pure avremo modo di mostrare nel seguito, ai singoli campi di struct puntate da appositi puntatori; questi saranno, ovviamente, puntatori a struct.

Capitolo 6

Nel documento Imparare il C una guida per Linux (pagine 54-64)

Documenti correlati