# \[C\] pointeur vers structures

**URL:** <https://www.debian-fr.org/t/c-pointeur-vers-structures/56209>\
**Category:** Programmation\
**Created:** [Février 21, 2016, 2:03 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209 "2016-02-21T14:03:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:03 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/1 "2016-02-21T14:03:34Z")

</div>

Salut,  
je suis en train de m’écrire un petit truc pour m’aider à tenir à jour mes cachets de musicien.  
Chaque cachet (“gig” en anglais) est une structure (date, lieu, groupe, salaire, etc…). Je voudrais gèrer tout les cachets en les groupant dans un tableau rangés selon leur date.  
L’idée ressemble un peu à une entreprise qui veut se créer un fichier contenant des infos sur ses employés.  
Déjà, est ce que ça vous semble raisonnable?  
L’idée serait ensuite de pouvoir calculer les sommes déclarées par mois/trimestre/année ou par groupe. J’ai essayé avec un simple tableur mais je ne sais automatiser ces calculs.

Voila où j’en suis:  
Cette fonction ne compile pas malgré la ligne presta = &tmp:

[code]gig\* create\_gig(void) {  
gig \*presta,tmp;

```
tmp.date = 0;
presta = &tmp;
scanf("Date: %d",presta->date);
return (presta);

```

}

functions.c:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘ **attribute** ’ before ‘\*’ token[/code]

Mon prototype:

[code]typedef struct gig {  
int date;  
// char \*place;  
// char \*band;  
// float pay;  
// int status;  
// char \*employer;  
// char \*misc;  
} gig;

gig\* create\_gig (void);[/code]

Le main.c est tout simple et j’utilise un makefile assez basique.

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 21, 2016, 2:03 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/2 "2016-02-21T14:03:35Z")

</div>

Une fois que j’ai corrigé l’utilisation du scanf.  
Pour essaie j’ai créé le fichier essaie.c : [pastebin.com/5XJg7i5c](http://pastebin.com/5XJg7i5c)  
que je compile sans makefile :

```auto

```

J’ai aucun warning.

---

<div class="post-metadata">

**Author:** ![jcsm33](https://www.debian-fr.org/user_avatar/www.debian-fr.org/jcsm33/32/3832_2.png) [@jcsm33](https://www.debian-fr.org/u/jcsm33)\
**Post date:** [Février 21, 2016, 2:03 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/3 "2016-02-21T14:03:37Z")

</div>

Le compilateur ne connaît pas gig et se plaint. Soit il manque le fichier gig.h qui va bien, soit la définition de gig est mal positionnée.

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:03 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/4 "2016-02-21T14:03:49Z")

</div>

Merci à vous deux. Mon erreur venait du fait que je n’avais pas inclu mon fichier .h. La definition de la strucuture n’apparaissait nulle part…

J’en profite.  
Sachant que je passe mes structures à travers des fnctions et qu’elles contiennent des chaines de caractères de longueur variables, vaut il meix faire qqchose du genre:

[code]struct mastructure {  
int \*p1  
char _p2  
char_ p3  
etc… } test;

int a;  
char s[10];

//remplir a et s;  
test-\>p1 = &a;  
test-\>p2 = s;[/code]

ou bien:

[code]struct mastructure {  
int a;  
char s[10];  
etc… } test;

//remplir directement la structure?[/code]

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 21, 2016, 2:03 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/5 "2016-02-21T14:03:49Z")

</div>

Ça dépend de pas mal de choses, mais je ne saurais que trop te recommander d’utiliser Bstring ([bstring.sourceforge.net/](http://bstring.sourceforge.net/)) qui permet d’éviter un tas d’erreur et de faille dans la gestion des string en C.

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 2:04 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/6 "2016-02-21T14:04:49Z")

</div>

Il n’y a aucun intérêt à utiliser des pointeurs pour les types de taille fixe comme int. Pour les chaînes, ça se discute mais si on utilise des pointeurs il vaut mieux savoir exactement ce qu’on fait : le pointeur pointe vers quelque chose, et il faut gérer l’allocation mémoire de ce quelque chose.

PS : rassure-moi, la vraie fonction create\_gig() ne contient pas le code que tu as montré, n’est-ce pas ? Tu es conscient qu’affecter à un pointeur l’adresse d’une variable locale automatique, puis retourner la valeur de ce pointeur en sortie est stupide ?

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:05 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/7 "2016-02-21T14:05:49Z")

</div>

> [@PascalHambourg](#):
>
> PS : rassure-moi, la vraie fonction create\_gig() ne contient pas le code que tu as montré, n’est-ce pas ? Tu es conscient qu’affecter à un pointeur l’adresse d’une variable locale automatique, puis retourner la valeur de ce pointeur en sortie est stupide ?

Ma fonction a changé un peu depuis mais je crois que c’est dangereux:

[code]char buffer[BUFSIZ];  
gig \*presta,tmp;

```
fflush(NULL);
presta = &tmp;

printf("Date: ");
fgets(buffer,sizeof(buffer),stdin);
presta->date = strtol(buffer,NULL,0);

```

…  
return(presta);[/code]

J’imagine que c’est foireux vu que je passe l’adresse d’une variable déclarée localement.  
Quelles solutions? utiliser malloc dans la fonction revient au même non?  
Il faut declarer la variable dans le main() et la passer en argument?

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 21, 2016, 2:05 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/8 "2016-02-21T14:05:49Z")

</div>

> [@silver.sax](#):
>
> utiliser malloc dans la fonction revient au même non?

Pas du tout, l’allocation mémoire ne se fait pas au même endroit (l’allocation automatique est sur la pile et l’autre sur le tas). Le tas est bien plus grand que la pile. Mais surtout la mémoire allouée sur la pile va être libérée automatiquement quand tu sort de la fonction.

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:05 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/9 "2016-02-21T14:05:50Z")

</div>

Ok.  
Donc si je retourne un pointeur vers une variable locale, cela revient à pointer vers un espace sur la pile. Je risque de voir mes données écrasées dès que je sors de la fonction?  
Il faut que le pointeur pointe vers un espace alloué sur le tas. J’utilise donc malloc, realloc. Ca m’eviterait de rajouter des variables dans le main().  
J’ai bon?

Malloc (et realloc) est il le seul à faire ça? Si je comprends bien, il faut faire des free dans ses fonctions sinon l’espace reste alloué est inaccessible une fois sortie de la fonction?

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 2:06 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/10 "2016-02-21T14:06:13Z")

</div>

Pour faire simple, l’allocation sous quelque forme (malloc, variable…) ne doit pas être faite dans la fonction appelée mais dans la fonction appelante ou au-dessus, puisque c’est cette dernière qui va utiliser le résultat.

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:06 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/11 "2016-02-21T14:06:42Z")

</div>

Ok, je vais m’y résoudre.  
Ca donnera pour un tableau de taille n:

`main ()
...
tab_gig = realloc(tab_gig,(n+1)*sizeof(gig*));
create_gig(tab_gig[n]);
n++;
...`

La fonction écrit directement dans tab\_gig[n]. C’est decidement la même chose qu’avec les tableaux.

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 2:06 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/12 "2016-02-21T14:06:48Z")

</div>

Pas sûr d’avoir compris ce que tu veux faire. Sauf erreur de ma part, d’après ton code l’espace mémoire pointé par tab\_gig contient des pointeurs vers des structures de type gig et non des structures de types gig. Dans ce cas il faut aussi allouer de la mémoire pour contenir les structures vers lesquelles pointent ces pointeurs. C’est bien ce que tu veux ?

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/13 "2016-02-21T14:07:01Z")

</div>

> [@PascalHambourg](#):
>
> Dans ce cas il faut aussi allouer de la mémoire pour contenir les structures vers lesquelles pointent ces pointeurs. C’est bien ce que tu veux ?

Au départ c’était mon idée et je pensais que cette allocation pouvait se faire dans la fonction appelée.  
J’ai fait comme ça car je ne voyais pas comment passer certaines cases en argument si je ne passais pas par des pointeurs.

Admettons que je decide d’utiliser un tableau de gig au lieu d’un tableau de gig\*. Comment faire pour passer l’adresse d’une case de mon tableau à une fonction afin de modifier cette case?

`tab_gig = malloc(n*sizeof(gig));
remplir_tab(tab_gig,n);
modif_tab(tab_gig[3]); ici on passe la variable pas valeur, pas de modif possible.
modif_tab(&tab_gig[3]);? équivalent à modif_gig(tab_gig+3)?`

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/14 "2016-02-21T14:07:01Z")

</div>

Ça dépend comment tu as défini tab\_gig. Si c’est comme gig \* (pointeur sur type structure gig), alors les deux formes de la dernière ligne, &tab\_gig[3] et tab\_gig+3, sont équivalentes en tant que pointeurs vers le 3e élément de type gig. La seconde forme a peut-être l’avantage de rappeler que tab\_gig est un pointeur et pas un tableau.

Dans l’avant-dernière ligne le commentaire est faux : il ne s’agit pas d’un passage par adresse (pointeur) mais au contraire par valeur. Comme c’est une copie de la variable qui est passée à la fonction, cette dernière ne peut modifier la variable originelle.

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/15 "2016-02-21T14:07:03Z")

</div>

Pour le commentaire, je voulais dire par valeur bien sûr. Etourderie, je corrige.

tab\_gig sera déclaré comme pointeur vers structure gig: `gig *tab_gig;` puis alloué dynamiquement.  
Je m’y mets.

Merci pour cette discussion enrichissante.

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/16 "2016-02-21T14:07:03Z")

</div>

> [@silver.sax](#):
>
> Au départ c’était mon idée et je pensais que cette allocation pouvait se faire dans la fonction appelée.

C’est tout à fait possible.

[code]$ less fic.c  
#include «&nbsp;stdio.h&nbsp;»  
#include «&nbsp;stdlib.h&nbsp;»

typedef struct gig {  
int date;  
} gig;

gig\* create\_gig (void) {  
gig\* tmp = malloc(sizeof(gig));  
tmp-\>date = 42;  
return tmp;  
}

int main (int argc, char\*\* argv) {  
gig\* foo = create\_gig();  
printf(«&nbsp;foo-\>date = %d\n&nbsp;», foo-\>date);  
free(foo);  
return EXIT\_SUCCESS;  
}  
$ CC=clang CFLAGS=-Wall make fic  
clang -Wall fic.c -o fic  
$ ./fic  
foo-\>date = 42[/code]

Ce n’est pas forcément recommandé car tu ne libère pas la mémoire au même endroit que tu ne l’alloue (mais avec une conception objet, tu crée un destructeur et ce n’est pas forcément plus mal).

> [@PascalHambourg](#):
>
> Ça dépend comment tu as défini tab\_gig. Si c’est comme gig \* (pointeur sur type structure gig), alors les deux formes de la dernière ligne, &tab\_gig[3] et tab\_gig+3, sont équivalentes en tant que pointeurs vers le 3e élément de type gig.

Non ça ne dépend pas de comment tu l’a défini. Ceci :

[code]#include «&nbsp;stdio.h&nbsp;»  
#include «&nbsp;stdlib.h&nbsp;»

void foo (int \* val) {  
printf(«&nbsp;foo = %d\n&nbsp;», \*val);  
}

int main (int argc, char\*\* argv) {  
int tab = {1, 2, 3};  
foo(tab+1);  
return EXIT\_SUCCESS;  
}[/code]  
fonctionne très bien.

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/17 "2016-02-21T14:07:03Z")

</div>

Oui, l’équivalence tableau/pointeur.  
J’esseairai de me souvenir de cette histoire d’allocation mémoire sur le tas (et penser à faire les free()).

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/18 "2016-02-21T14:07:05Z")

</div>

> [@MisterFreez](#):
>
> Non ça ne dépend pas de comment tu l’a défini. Ceci (…) fonctionne très bien

Je ne vois pas ce que ton exemple est censé montrer ni en quoi il contredit ce que j’ai écrit.  
Si le pointeur n’est pas défini avec le type approprié (void…), alors le calcul de l’offset ne sera pas fait correctement à moins de faire un cast explicite. C’est tout ce que je voulais dire.

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 21, 2016, 2:07 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/19 "2016-02-21T14:07:05Z")

</div>

Ok on s’est mal compris j’ai pensais que tu faisais une différence entre une déclaration comme pointeur (type \* ident) et un tableau (type ident []). Pour le typage ça me semblait une évidence.

---

<div class="post-metadata">

**Author:** ![Funkygoby](https://www.debian-fr.org/user_avatar/www.debian-fr.org/funkygoby/32/3984_2.png) [@Funkygoby](https://www.debian-fr.org/u/Funkygoby)\
**Post date:** [Février 21, 2016, 7:45 UTC](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209/20 "2016-02-21T19:45:17Z")

</div>

Salut,  
je continue sur mon projet et j’ai réglé pas mal de problèmes en ayant prit conscience de l’existence de la pile et du tas -\> obligation d’utiliser malloc ou realloc dans mon cas (j’utilisais des variables locales :/)

Par contre j’ai un problème lorsque je récupère mon tableau dans la fonction appelante. Il faut que la fonction appelée retourne le pointeur sinon il y a un seg fault dès que je veux lire mon tableau apparement.  
Je me rappelle pas être tombé sur un truc comme ça avant!  
Je pensais que c’était justement l’avantage de manipuler des pointeurs: pouvoirs manipuler les valeurs de la fonction appelante.

Ex: foo est une fonction bidon qui fait un realloc d’une case donne une valaur à tab[0] puir return(tab).

[code]int main () {  
int \*tab = NULL;

```
foo(tab);
//tab = foo(tab);

printf("%d\n",tab[0]);
	
return (0);

```

}[/code]

Un seg fault se produit avec le printf. Il faut utiliser la ligne commentée. Ca m’ennuie car j’écrivais mes fonctions de manière à ce qu’elle modifie mon tableau/pointeur (édition, rajout, suppression de case) et retourne le nombres d’éléments.

Ma question est:  
J’écris une fonction (pour lire mon tableau à partir d’un fichier). Comment je fais pour recupèrer mes données et la taille du tableau?

Dans le cas d’un tableau d’entier ou de float, on pourrait peut être utiliser sizeof pour trouver le nombres d’éléments mais est ce que ça marche pour des structures contenant des chaines de caractères dynamique?  
J’ai lu des forums où il est question de tab-1 où serait stocker le nombres d’éléments.

D’ailleurs comment est géré la mémoire dans un tableau où chaque case est de taille différente? l’incrémtation tab+1 est toujours valide?

[Page suivante](https://www.debian-fr.org/t/c-pointeur-vers-structures/56209.md?page=2)
