Envoyé par Médinoc
Envoyé par Médinoc
Pas de Wi-Fi à la maison : CPL
Je suppose que vous voulez dire:Envoyé par Emmanuel Delahaye
En effet, mais l'utilisateur étourdi (qui pourrait très bien être moi ) n'a qu'à faire attention. Le C laisse beaucoup de libertés au programmeur et suppose que ce dernier sait ce qu'il fait.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 #undef N #define N 100
Oui, déjà corrigé.Envoyé par stephl
Pas de Wi-Fi à la maison : CPL
Dans une union, on ne peut acceder qu'au dernier membre ecrit, ici b. Donc lire a est normalement interdit mais il y a une exception: quand l'union est une union de struct qui commencent par les memes champs, on peut acceder aux champs communs.Envoyé par souviron34
Modifions legerement le code pour voir facilement comment du code incorrect peut etre genere:
Prenons une architecture little endian avec un char non signe. Le compilateur peut decider que sizeof(struct a) va valoir 4 comme un int pour des raisons de perf. Il peut aussi decider de maintenir le padding a 0. De meme sizeof(struct b) va valoir 4 et il va y avoir un peu moins de padding.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 struct a { char c; }; struct b {char c; char d; }; union u { struct a a; struct b b }; int getCFromA(struct a) { return a.c; } int getCFromU(union u) { return u.a.c; } union uu; ... uu.b.c = 'a';
Lire a.c et le transformer en int consiste donc a ajouter des 0.
getCFromA peut considerer que le padding est toujours present et valant 0. Donc lire simplement l'int qui se trouve a l'addresse.
Dans getCFromU, le compilateur ne peut pas generer un code aussi simple et se fier au padding. Il doit lire le char tout seul et l'etendre avec des 0 pour masquer la valeur eventuelle de u.b.d.
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
D'abord une remarque ..
J'ai compilé ton code, Jean-Marc, sur mon Linux (redhat 7.3) (la fonction f) et voici ce que j'obtiens :
Pour rappel, la ligne 5 est la ligne de définition de p1 (compilé avec -Wall -pedantic)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 .//test1.c: In function `f': .//test1.c:5: warning: initialization from incompatible pointer type .//test1.c:6: warning: unused variable `p2' .//test1.c:5: warning: unused variable `p1'
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".
Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java
Je ne réponds pas aux MP techniques
Quant à l'autre problème, je comprend ce que tu veux dire, mais il me semblait que la définition même d'une union était que l'adresse physique de départ était la même. Et que, réservant la place la plus grande (en l'occurence ici pour la structure b), si le(s) premier(s) élément(s) a(ont) la même taille, quelque soit ce qu'il y a derrière, physiquement c'est écrit au même endroit...
Et que dans ce cas (et uniquement dans ce cas) accèder l'un ou l'autre est rigoureusement identique...
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".
Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java
Je ne réponds pas aux MP techniques
Les structures a et b commençant par les même champs, je ne comprends pas pourquoi getCFromA(uu.a) n'est pas conforme?Envoyé par Jean-Marc.Bourguet
Thierry
"The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
"If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow
FAQ-Python FAQ-C FAQ-C++
+
Les deux structs peuvent avoir la meme taille a cause du padding. Le compilateur peut faire des suppositions sur le padding (par exemple qu'il est toujours a 0) dans getCFromA et s'arranger pour que toutes les modifications d'une struct a respectent ces hypotheses et donc generer du code commeEnvoyé par souviron34
en supposant une convention telle que les struct tenant dans un registre sont passees dans le registre P0 qui en sortie de fonction contient un resultat entier.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 getCFromA: ret getCFromU: and P0,P0,#0x000000FF ret
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Je veux bien qu'elles puissent avoir la même taille, mais le début est forcément physiquement à la même adresse, non ??Envoyé par Jean-Marc.Bourguet
Donc si j'écris un char et que les 2 structures commencent par un char, le char commence et se termine au même endroit dans les 2 structures, non ??
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".
Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java
Je ne réponds pas aux MP techniques
Oui. Mais quand on accede au char par un struct a, le compilateur peut faire ce qu'il veut sur le padding. Supposer qu'il est toujours mis a 0 par exemple. Ou supposer qu'il peut l'ecraser. Ces suppositions ne sont pas valides quand il fait acces a un struct b. Elles ne sont pas non plus valides quand il fait acces a un struct a qui se trouve dans une union contenant un struct b. (D'ou le masquage du dernier octet dans mon exemple).Envoyé par souviron34
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
J'ai déjà lu quelqu'un gueuler sur ce sujet ici.Envoyé par Emmanuel Delahaye
Essaie ceci:
Ceci marche sous Visual 2005 en C comme en C++, et il me semble avoir lu ici que ça ne marche pas en C sous gcc.
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 char ** ppCh1 = NULL; char const * const * pcpcCh2 = ppCh1;
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Ce qui est normal, gcc a raison. Les règles du C et du C++ sont différentes. En C, on ne peut ajouter const qu'au niveau le plus extérieur:Envoyé par Médinoc
Et à regarder rapidement, c'est ce qui bloque Emmanuel aussi.
Code : Sélectionner tout - Visualiser dans une fenêtre à part char* const* ppcCh3 = ppCh1;
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager