Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/wikka.php on line 315 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/libs/Wakka.class.php on line 176 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/libs/Wakka.class.php on line 463 Deprecated: Function set_magic_quotes_runtime() is deprecated in /home/demetres/public_html/didattica/ae/wikka.php on line 120 Deprecated: Function ereg() is deprecated in /home/demetres/public_html/didattica/ae/libs/Wakka.class.php on line 648 Ingegneria degli Algoritmi: Lezione 5 - Lunedì 10 marzo 2014 (180 min)

Ingegneria degli Algoritmi

Corso di Laurea in Ingegneria Informatica e Automatica - A.A. 2014-2015

HomePage | Avvisi | Diario lezioni | Programma | Materiale didattico | Esami | Forum | Login
Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/safehtml.php on line 308 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 159 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 161 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 162 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 163 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 165 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 166 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 167 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 243 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 250 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 259 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 266 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 273 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 280 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 467 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 469 Deprecated: Assigning the return value of new by reference is deprecated in /home/demetres/public_html/didattica/ae/3rdparty/core/safehtml/classes/HTMLSax.php on line 471

Lezione 5 - Lunedì 10 marzo 2014 (180 min)



[ << Lezione precedente | ^ Diario delle lezioni | >> Lezione successiva ]

Argomenti: Tipi struttura, typedef, espressioni che denotano tipi

Descrizione dettagliata:


Appunti della lezione


Strutture

Come gli array, anche le strutture sono aggregati di oggetti. Il tipo struttura è un tipo composto che specifica il numero e tipo dei campi di un aggregato. Diversamente dagli array, che sono aggregati di oggetti di tipo omogeneo, in una struttura i campi possono avere tipo diverso.

Dichiarazione di struttura: una struttura si dichara come nell'esempio seguente.

struct S {
    int x, y;
    double z;
};


La dichiarazione introduce un tipo struttura S costituito da due int e un double, identificati rispettivamente dai nomi dei campi x, y e z. Il tipo struttura dichiarato è identificato dal tag struct S.

Spazio dei nomi tag delle strutture: i tag delle strutture formano uno spazio di nomi distinti da quelli degli altri identificatori (es. di variabili, ecc.).

Esempio:

struct x { int a, b; };
int x; // legale, poiché x è diverso da struct x


Dichiarazione di variabili struttura: Il seguente frammento di programma dichiara una variabile v di tipo struct S:

struct S v;


La dimensione di una struttura sarà almeno pari alla somma delle dimensioni dei suoi campi. Nel nostro esempio: sizeof(struct S) >= sizeof(int) + sizeof(int) + sizeof(double). Vedremo più avanti perché potrebbe non valere l'uguaglianza stretta.

Accesso ai campi di una struttura: per accedere ai campi di una struttura è possibile usare l'operatore . (punto). Se E è un Lvalue di tipo struttura e c è un suo campo, allora l'espressione E.c è un Lvalue che denota il campo c della struttura E.

Esempi:

v.x = 10;   // scrittura campo x
v.y = 20;   // scrittura campo y
v.z = 3.14; // scrittura campo z
printf("x=%d, y=%d, z=%f\n", v.x, v.y, v.z); // lettura di campi di una struttura


Puntatori a strutture: mostriamo ora come accedere ai campi di una struttura mediante un puntatore.

Esempio:

struct S* p;
p = malloc(sizeof(struct S)); // allocato in heap spazio per contenere un oggetto struct S
(*p).x = 10;
(*p).y = 20;
(*p).z = 3.14;


Si noti che, poiché l'operatore . (punto) ha priorità più alta dell'operatore *, è necessario usare le parentesi per specificare che si intende accedere all'oggetto *p puntato da p.

Operatore -> per accedere ai campo di una struttura: per rendere più agevole l'accesso ai campi di una struttura, in C è possibile usare l'operatore -> come forma abbreviata: se E è un puntatore a una struttura che ha un campo c, allora E->c è equivalente a (*E).c.

Esempio:

struct S* p;
p = malloc(sizeof(struct S)); // alloca in heap spazio per contenere un oggetto struct S
p->x = 10;                    // equivalente a (*p).x = 10;
p->y = 20;                    // equivalente a (*p).y = 20;
p->z = 3.14;                  // equivalente a (*p).z = 3.14;


Strutture sono Lvalue modificabili: le espressioni che denotano oggetti struttura sono Lvalue modificabili. Pertanto, è possibile assegnare una struttura all'altra:

struct S v;
struct S q;
...
v = q; // ok, copia byte a byte del contenuto di q in v


Allo stesso modo, è possibile passare una struttura come parametro per copia a una funzione:

void foo(struct S q) {
    q.x = 55; // modifica la copia locale della struttura, non la variabile v del main...
    q.y = 12;
    q.z = 7.9;
}

int main() {
    struct S v;
    v.x = 10;
    v.y = 20;
    v.z = 3.14;
    foo(v); // passaggio di parametro struttura per copia: copia byte a byte del contenuto di v nel parametro formale q di foo
    printf("x=%d, y=%d, z=%f\n", v.x, v.y, v.z); // stampa x=10, y=20, x=3.14
    return 0;
}


Poiché il passaggio per copia potrebbe essere inefficiente, soprattutto per strutture di grandi dimensioni, è possibile passare una struttura per indirizzo. Oltre a essere più efficiente, poiché viene passato solo un indirizzo invece dell'intera struttura, questo consente anche di fare side-effect sull'oggetto passato:

void foo(struct S* q) {
    q->x = 55; // fa side-effect sulla variabile v del main...
    q->y = 12;
    q->z = 7.9;
}

int main() {
    struct S v;
    v.x = 10;
    v.y = 20;
    v.z = 3.14;
    foo(&v); // passaggio di parametro struttura per indirizzo: copia dell'indirizzo di v nel parametro formale q di foo permette a foo di modificare v
    printf("x=%d, y=%d, z=%f\n", v.x, v.y, v.z); // stampa x=55, y=12, x=7.9
    return 0;
}


Esempio delle liste collegate.

Le strutture insieme ai puntatori permettono di realizzare strutture dati collegate. Consideriamo ad esempio una lista collegata semplice di interi. Il tipo nodo della lista può essere dichiarato come segue:

struct node {
    int elem;
    struct node* next;
};


Dove elem è il dato contenuto nel nodo e next il puntatore al prossimo nodo della lista. Un nodo può essere creato e inizializzato come segue:

struct node* p;                  // dichiara variabile puntatore a nodo
p = malloc(sizeof(struct node)); // alloca spazio in heap per il nodo
p->elem = 10;                    // inizializza campo dato del nodo a 10
p->next = NULL;                  // non c'è un successore nella lista
...
free(p);                         // dealloca il nodo



Dichiarazioni di identificatori di tipo mediante typedef

Usando al parola chiave typedef, in C è possibile definire degli identificatori di tipo che possono essere usati come alias di altri tipi, cioè come nomi equivalenti.

Esempio:
typedef int intero;    // dichiara l'identificatore intero come alias di tipo per int
intero x[10];          // x è una variabile di 10 int

typedef char* stringa; // dichiara l'identificatore stringa come alias di tipo per char*
stringa s;             // s è una variabile di tipo char*

typedef struct S S;    // dichiara l'identificatore S come alias di tipo per struct S
S* v;                  // v è una variabile di tipo puntatore a struct S


Espressioni che denotano tipi

Tutorial (in inglese)


Materiale didattico per la lezione




Esercizi del giorno


Esercizio 1

Si consideri la seguente dichiarazione di un nodo di una lista collegata di interi:

typedef struct node {
    int elem;
    struct node* next;
} node;


  1. Scrivere una funzione nodo* add(int elem, node* list) che, dato un puntatore al primo nodo di una lista, o NULL per indicare una lista vuota, inserisce in testa alla lista un nuovo nodo contenente il dato elem, e restituisce il puntatore al nodo creato.
  2. Scrivere una funzione void print(node* list) che, data una lista, ne stampa il contenuto nel formato: [elem1, elem2, elem3, ...].
  3. Scrivere una funzione void delete(node* list) che, data una lista, ne dealloca tutti i nodi.

Usare il seguente programma di prova:

main.c
#include <stdio.h>

typedef struct node {
    int elem;
    struct node* next;
} node;

// mettere qui la definizione delle funzioni add, print e delete

int main() {
    node* list = add(5, add(3, add(2, add(7, add(4, add(1, add(6, NULL)))))));
    print(list); // stampa: [5, 3, 2, 7, 4, 1, 6]
    delete(list);
    return 0;
}


Verificare con memcheck (Valgrind) che il programma usi la memoria correttamente.

Esercizio 2 (espressioni di tipo)

Si traduca in C la seguente dichiarazione di variabile usando le regole sulla specifica di espressioni di tipo (si veda [P2]):

"v è un array di 64 puntatori a puntatori a funzione che prende come parametro un puntatore a funzione senza argomenti che restituisce un puntatore a un array di 16 float, e restituisce un puntatore a funzione con due argomenti int che restituisce void."

Esercizio 3 (espressioni di tipo)

Si traduca in italiano la seguente dichiarazione C:

int (*(*p)[7])(int *(*f[20])(float** m, int r), void* q[20]);

Esercizio 4 (espressioni di tipo)

Si traducano in italiano le seguenti dichiarazioni C:

  1. char ****q[30];
  2. char **(**q)[30];
  3. int (x)[];
  4. long (*a[])( char, char );
  5. int *(*(*(*b)())[10])();
  6. char *strprt( char (*)( int ), unsigned char );
  7. int (*ab[])( unsigned int );

Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by Wikka Wakka Wiki 1.1.6.3
Page was generated in 0.0612 seconds