TD4 : Pointeurs, Copies profondes

3

struct s1 { int i; };
struct s2 { struct s1 s; };
struct s3 { struct s1 *p; };

14.

NB : b->s = (*b).s

struct s1 *a = malloc(sizeof(struct s1));

(*a).i = 42; // ou : a->i=42;

struct s2 *b = malloc(sizeof(struct s2));

b->s=*a;
digraph structs {
node [shape=record];
struct1 [shape=record,label="<f0>a"];

struct2 [shape=record,label="<f0> i=42"];

struct3 [shape=record,label="<f0>b"];

struct4 [shape=record,label="<f0> i=42"];


struct1:f0 -> struct2:f0;
struct3:f0 -> struct4:f0;

 }

15

struct s1 s1; // oui, on peut donner le meme nom a une
struct s2 s2; // variable et a un type struct...
struct s3 s3, ss3;
s1.i = 42; s2.s1 = s1;
s3.p = &s1;
ss3.p = malloc (sizeof (struct s1)); ss3.p->i = 54;
  • La pile : on y met les variables locales, etc..
  • Le tas : où se retrouvent les données “mallocées” : bien moins ordonné

16

*f(void) VS *f() :

  • *f(void) : ne prend jamais aucun argument
  • *f() : ne prend pas, a priori, d’argument, mais ne renvoie pas d’erreur si on lui en donne.
struct s1 *f(void) {
struct s1 s;
s.i = 42;
return &s;
}

gros pb : &s : tout est effacé à la sortie de la fonction, quand pile dépilée vers l’adresse de retour. (structure libérée après l’appel)

Pour pallier ce pb : malloc : survit après l’appel de la fonction.

17

struct s3 *f(void) {
struct s1 s; s.i = 9;
struct s3 *p3 = malloc (sizeof (struct s3));
p3->p = &s;
return p3;
}

même problème : le pointeur p ne pointe vers plus rien, après l’appel de la fonction

Correction :

struct s3 *f(void) {
a = malloc(sizeof struct s1);
a->i=9;
struct s3 *p3 = malloc (sizeof (struct s3));
p3->p = a;
return p3;
}

19

La première : taille infinie en mémoire.

20

En Java (comme en CamL, d’ailleurs), déclarer un type, c’est déclarer un pointeur vers ce type. Donc ça revient à la deuxième option de la question précédente (en C).

21

En C : comme l’inclusion de structures est autorisées :

  • économie de mémoire
  • permet des copies en dur : modification de l’une ne modifie pas l’autre

Ex :

  • Graphport pour les premiers Macs : pour imprimer (avec des pointeurs).

22

Ca marche sans, et de toute façon : on n’utilise pas de pointeurs dans ces langages.

23

void *memchr(const void *s, int c, size_t n);

void * : pointeur générique, vers n’importe quel type.

void *memchr(const void *s, int c, size_t n){
    size_t i;
    const unsigned char *sp=s;
    unsigned char cc;
    for(i=0; i<n; i++){
        cc = *sp++;
        if (cc == c)
            return sp-1
    }
    return NULL;
}

Leave a comment