Discussion:Programmation C/Types avancés
Un livre de Wikibooks.
[modifier] Alignement et bourrage (padding)
J'ai supprimé l'exemple suivant de code pour offsetof:
long distance = (long) &((struct ma_structure *)NULL)->champ;
Mis à part le fait que le type est size_t (au moins dans le n1124), il utilise une conversion d'une valeur de type pointeur vers un type entier, ce qui n'est pas portable. J'ai ensuite rapidement pensé à
static ma_structure s; size_t distance = &s.champ - &s;
Mais les types sont incompatibles. Deux casts vers (void*) ne résolvent pas encore les choses, car la soustraction de pointeurs ne se fait que pour des pointeurs sur objets (void* est donc exclu). Caster en (unsigned char*)(void*) serait donc encore mieux, mais il reste la contrainte qu'on ne peut soustraire que dans un tableau... Ne sachant plus à quel point il est portable de traiter une structure comme un tableau de unsigned char, et donc si cette soustraction serait définie par la norme, j'ai préféré laisser tomber l'exemple. Si une référence exacte de la norme permet de le valider, alors on peut le mettre dans le texte. Alveric 21 juillet 2006 à 11:57 (CEST)
- Mouais, ce n'est pas parce que ce n'est pas écrit noir sur blanc dans la norme, que ce n'est pas forcément portable. Intuitivement, on voit bien que ce genre d'expression fait le boulot qu'on lui demande. Je ne prendrais pas trop de risque en disant que 100% des implémentations d'offsetof utilise une astuce de ce genre. J'ai beau me creuser les méninges, je ne vois vraiment pas ce qui pourrait faire foirer cette expression, et crois moi que s'il y en avait ne serait-ce qu'une, même infime, je ne l'aurais pas mise. Ah, ouais et si possible une raison autre que c'est_pas_dans_la_norme™, parce qu'à ce petit jeu là on peut enculer les mouches très profond. Peut-être avec une archie qui utilise une segmentation de la mémoire style 286, et encore j'en doute. Thierry Pierron 21 juillet 2006 à 16:10 (CEST)
- Je suis d'accord que le nombre d'implémentations où le code foirerait doit être proche de 0... J'ai vérifié dans le Rationale du C89 (page 151 du pdf):
- The
offsetofmacro was added to provide a portable means of determining the offset, in bytes, of a member within its structure. This capability is useful in programs, such as are typical in database implementations, which declare a large number of different data structures: it is desirable to provide "generic" routines that work from descriptions of the structures, rather than from the structure declarations themselves. - In many implementations,
offsetofcould be defined as one of (size_t)&(((s_name*)0)->m_name)- or
(size_t)(char*)&(((s_name*)0)->m_name)- or, where X is some predeclared address (or 0) and A(Z) is defined as ((char*)&Z),
(size_t)(A((s_name*)X->m_name ) - A(X))- It was not feasible, however, to mandate any single one of these forms as a construct guaranteed to be portable. Some implementations may choose to expand this macro as a call to a built-in function that interrogates the translator’s symbol table.
- The
- On est donc d'accord, et le Rationale le dit bien, many implementations mais pas guaranteed to be portable. Je vais quand même remettre l'exemple, car il peut (peut-être) permettre une meilleure compréhension, mais en précisant que
offsetofest la seule manière strictement portable de le faire. Alveric 26 juillet 2006 à 12:18 (CEST)- Moui, j'ai juste un peu retravaillé le texte pour que l'enchainement soit plus naturel. Sinon j'ai traduit "bytes" par "mot machine". Désolé ça me fait trop mal aux yeux de voir ce mot anglais.Thierry Pierron 26 juillet 2006 à 15:53 (CEST)
- Ok pour tes modifs, à part que je ne trouve pas
offsetofsi contraignante que ça... Mais bon, c'est subjectif. Alveric 26 juillet 2006 à 16:43 (CEST)- Bah, le problème avec cette macro, c'est que tu ne peux pas lui transmettre un type pointeur. Pour peu que tu fasses une définition de ce genre :
typedef struct { /* bla bla */ } * mon_type;- Pouf, la macro est inutilisable.Thierry Pierron 26 juillet 2006 à 17:42 (CEST)
- Ok pour tes modifs, à part que je ne trouve pas
- Moui, j'ai juste un peu retravaillé le texte pour que l'enchainement soit plus naturel. Sinon j'ai traduit "bytes" par "mot machine". Désolé ça me fait trop mal aux yeux de voir ce mot anglais.Thierry Pierron 26 juillet 2006 à 15:53 (CEST)
- Je suis d'accord que le nombre d'implémentations où le code foirerait doit être proche de 0... J'ai vérifié dans le Rationale du C89 (page 151 du pdf):
Okay, j'ai encore charcutée cette section qui était devenu imbitable, à force de rappel, contre-rappel, précision, remarques, note, etc ... Bon le but de cette section ce n'est pas d'expliquer la vie, l'univers et le tout le reste mais simplement de faire remarquer que : les champs des structs ne se suivent pas en mémoire, il y a des octets de bourrages, et d'illustrer par un exemple proche (mais pas forcément exact) de ce qui se passe dans la réalité.
Rappeler que les char peuvent faire plus que 8bits, on le sait, on l'a mattraqué dans la section relatif aux types de bases. Dans cet exemple, char = 8bits. Point barre.
Dans la réalité il y a tellement de cas de figures qu'essayer d'en effleurer les possibilités rendrait le texte complètement imbitable (on n'en était pas là, mais on suivait ce chemin). Thierry Pierron 25 juillet 2007 à 22:13 (CEST)
[modifier] Unions
Le code suivant, donné en exemple, utilise des structures et une union anonymes:
struct {
int type;
union {
struct {
struct point *p1, *p2;
};
struct {
struct point *p;
struct droite *d;
};
};
} droite;
Or il me semble que ces constructions ne sont pas valides en C (GCC ne les aime ni en mode C90, ni en mode C99), seul le C++ les définit, et certains compilateurs C en tant qu'extension (dont GCC en mode "gnu89" et "gnu99" et quelques uns que j'ai trouvés sur google). Quelqu'un pour confirmer ? Alveric 26 juillet 2006 à 12:18 (CEST)
- Arf, exact. En plus l'exemple est vraiment pourri, il ne montre même pas comment on s'en sert (accès aux champs). Même les struct anonymes me paraissent douteuses. Je vais changer ça. Thierry Pierron 26 juillet 2006 à 15:30 (CEST)