tableau souple

Le
PIGUET Bruno
Bonjour,

Pour créer, puis parcourir, un tableau constant (au sens du langage C),
mais pouvant évoluer (au fil des différentes versions), sans m'embêter
avec des #define NB_VAL ou autre, j'utilise un idiome basé sur sizeof
(tab) / sizeof (*tab) (voir l'ECM en PS).

Les avisés lecteurs de ce newsgroup ont-il un avis sur cette
technique ? Y-a-t'il un danger caché ? Avez-vous autre chose à
recommander ?.

Merci d'avance,

Bruno.

PS : voici l'ECM :

#include<stdio.h>

int
main ()
{
char *villes[] = { "Paris", "Lyon", "Toulouse" };
int i;

for (i = 0; i < sizeof (villes) / sizeof (*villes); i++)
{
printf ("%d : %s", i, villes[i]);
}
return 0;
}
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
espie
Le #21553031
In article PIGUET Bruno
Bonjour,

Pour créer, puis parcourir, un tableau constant (au sens du langage C),
mais pouvant évoluer (au fil des différentes versions), sans m'embêter
avec des #define NB_VAL ou autre, j'utilise un idiome basé sur sizeof
(tab) / sizeof (*tab) (voir l'ECM en PS).

Les avisés lecteurs de ce newsgroup ont-il un avis sur cette
technique ? Y-a-t'il un danger caché ? Avez-vous autre chose à
recommander ?.



Il y a un danger pas trop bien cache: le jour ou tu passes a malloc
pour ton tableau, ca ne marche plus.
PIGUET Bruno
Le #21553231
Le Wed, 14 Apr 2010 08:50:20 +0000, Marc Espie a écrit :

Il y a un danger pas trop bien cache: le jour ou tu passes a malloc pour
ton tableau, ca ne marche plus.



Je n'envisage pas de passer à malloc() dans ce cas : c'est vraiment
pour un tableau constant codé en dur dans le code, mais dont le nombre
d'éléments peut changer d'une version à l'autre.
Ce n'est pas pour une fonction de bibliothèque, qui ne pourrait
effectivement pas faire d'hypothèse sur l'origine du tableau.

Bruno.
FX
Le #21553491
PIGUET Bruno a écrit :
Bonjour,

Pour créer, puis parcourir, un tableau constant (au sens du langage C),
mais pouvant évoluer (au fil des différentes versions), sans m'embêter
avec des #define NB_VAL ou autre, j'utilise un idiome basé sur sizeof
(tab) / sizeof (*tab) (voir l'ECM en PS).

Les avisés lecteurs de ce newsgroup ont-il un avis sur cette
technique ? Y-a-t'il un danger caché ? Avez-vous autre chose à
recommander ?.



N'oublie pas de mettre les sizeof entre parenthèses.
PIGUET Bruno
Le #21553941
Le Wed, 14 Apr 2010 12:07:24 +0200, FX a écrit :

N'oublie pas de mettre les sizeof entre parenthèses.



Ah, tiens ?
Pourquoi ?

En général, j'entoure de parenthèse les macros qui risquent de produire
quelque chose comme : a-b. Avec les parenthèses, le compilateur comprend
bien : (a1-b1)/(a2-b2) et pas : a1 - b1/a2 -b2.

Mais sizeof() n'est pas un macro, que je sache ?

Bruno.
Antoine Leca
Le #21553721
FX écrivit :
PIGUET Bruno a écrit :
sur sizeof (tab) / sizeof (*tab) (voir l'ECM en PS).



N'oublie pas de mettre les sizeof entre parenthèses.



Peut-on avoir plus de détails sur la position des parenthèses
supplémentaires que tu proposes et la raison de ta recommandation ?

Surtout que même si je comprend tout-à-fait la position de Bruno de
mettre des parenthèses en réalité inutiles mais qui évitent de se poser
des questions, j'ai l'habitude d'écrire le contraire :
sizeof tab / sizeof*tab

Et je ne vois pas de raison de mettre un appel de fonction ou un
indiçage (genre 2[villes]) derrière une expression comme celle-ci.


Antoine
Éric Lévénez
Le #21553711
Le 14/04/10 12:50, Antoine Leca a écrit :
FX écrivit :
PIGUET Bruno a écrit :
sur sizeof (tab) / sizeof (*tab) (voir l'ECM en PS).



N'oublie pas de mettre les sizeof entre parenthèses.



Peut-on avoir plus de détails sur la position des parenthèses
supplémentaires que tu proposes et la raison de ta recommandation ?

Surtout que même si je comprend tout-à-fait la position de Bruno de
mettre des parenthèses en réalité inutiles mais qui évitent de se poser
des questions, j'ai l'habitude d'écrire le contraire :
sizeof tab / sizeof*tab



Moi j'écris :

i < (int)(sizeof tab / sizeof *tab)

car comme le sizeof est non signé, je préfère masquer le warning du
compilateur. Mais tout cela ne marche que si la taille tient dans un int
signé.

--
Éric Lévénez
FAQ de fclc :
PIGUET Bruno
Le #21554311
Le Wed, 14 Apr 2010 12:59:23 +0200, Éric Lévénez a écrit :


Moi j'écris :

i < (int)(sizeof tab / sizeof *tab)

car comme le sizeof est non signé, je préfère masquer le warning du
compilateur. Mais tout cela ne marche que si la taille tient dans un int
signé.



En fait, moi je penche plutôt pour définir i comme un size_t.

Mais alors, pour le printf, le format n'est plus %d, et on doit choisir
entre %lu (ce qui marche "en général", pour compilos C89) et %zd (en C99).
J'évite la solution passe-partout mais lourdingue :
écrire toujours %lu et en castant le size_t en unsigned long :
printf("%lu", (unsigned long) i);

Bruno.
PIGUET Bruno
Le #21554301
Le Wed, 14 Apr 2010 13:44:01 +0200, FX a écrit :


Je pensais aux parenthès qui englobent les 2 sizeof:

#define NUM_ELEM(tab) ( sizeof(tab) / sizeof(*tab) )
^ ^



Ah, OK, si je définis une macro qui englobe les sizeof.
effectivement, là, il vaut mieux.
Mais alors, pour la légèreté de la chose, on peut arriver à (cf message
d'Antoine) :

#define NUM_ELEM(tab) (sizeof tab / sizeof *tab)

J'ai vu parfois aussi, pour ceux qui préfèrent les notations tableaux aux
pointeurs :

#define NUM_ELEM(tab) (sizeof tab / sizeof tab[0])

Bruno.
espie
Le #21554411
In article à ric Lévénez
Le 14/04/10 12:50, Antoine Leca a écrit :
FX écrivit :
PIGUET Bruno a écrit :
sur sizeof (tab) / sizeof (*tab) (voir l'ECM en PS).



N'oublie pas de mettre les sizeof entre parenthèses.



Peut-on avoir plus de détails sur la position des parenthèses
supplémentaires que tu proposes et la raison de ta recommandation ?

Surtout que même si je comprend tout-à-fait la position de Bruno de
mettre des parenthèses en réalité inutiles mais qui évitent de se poser
des questions, j'ai l'habitude d'écrire le contraire :
sizeof tab / sizeof*tab



Moi j'écris :

i < (int)(sizeof tab / sizeof *tab)

car comme le sizeof est non signé, je préfère masquer le warning du
compilateur. Mais tout cela ne marche que si la taille tient dans un int
signé.



Ca serait mieux que le compilo ne fasse pas chier et apprenne a reconnaitre
ce genre d'idiomes et ne pas donner d'avertissements inutiles.

Je suis de moins en moins fan des cast "pour faire joli", surtout qu'un
jour, on change du code, et hop, le gentil cast se transforme en
pointer -> int ou autre joyeusete.

C'est tres dommage que C n'ait pas importe un equivalent des casts modernes
de C++. Meme si on peut ne pas aimer la syntaxe, c'est une vraie bonne
idee...
zwim
Le #21556701
Le Wed, 14 Apr 2010 08:40:26 +0000 (UTC)
PIGUET Bruno a écrit
Bonjour,

Pour créer, puis parcourir, un tableau constant (au sens du langage C),
mais pouvant évoluer (au fil des différentes versions), sans m'embêter
avec des #define NB_VAL ou autre, j'utilise un idiome basé sur sizeof
(tab) / sizeof (*tab) (voir l'ECM en PS).

Les avisés lecteurs de ce newsgroup ont-il un avis sur cette
technique ? Y-a-t'il un danger caché ? Avez-vous autre chose à
recommander ?.

Merci d'avance,

Bruno.

PS : voici l'ECM :

#include
int
main ()
{
char *villes[] = { "Paris", "Lyon", "Toulouse" };
int i;

for (i = 0; i < sizeof (villes) / sizeof (*villes); i++)
{
printf ("%d : %sn", i, villes[i]);
}
return 0;
}



Pour changer un peu le fil de la discussion, il y a aussi possibilité
de faire comme avec les chaines de caractères des tableaux AZT (à zéro
terminal) et ainsi s'affranchir du nombre d'éléments.

La valeur terminale dépendra des données, par exemple -1 pour un
tableau de nbr positifs, NULL, "", ou tout autre valeur qu'on puisse
différentier des valeurs potentiellement utilies.

#include
int main (void)
{
char *villes[] = { "Paris", "Lyon", "Toulouse", NULL };
int i;

for (i = 0; villes[i]; i++)
{
printf ("%d : %sn", i, villes[i]);
}

return 0;
}

--
zwim.
Rien n'est impossible que la mesure de la volonté humaine...
Publicité
Poster une réponse
Anonyme