Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Union de deux tableaux 4x4 et 1x16

14 réponses
Avatar
Thierry B.
Bonjour le monde.

Question simple, avec un ECM:

-----------------------------------------------
#include <stdio.h>
typedef union
{
char s[4][4];
char l[16];
} machin;
int main(int argc, char *argv[])
{
int x, y, i;
machin m;
/* remplir le machin */
for (i=0; i<16; i++)
m.l[i] = i;
/* afficher le machin */
for (x=0; x<4; x++)
{
for (y=0; y<4; y++)
printf("%2d ", m.s[x][y]);
puts("");
}
return 0;
}
-----------------------------------------------

Ai-je raison de penser que ces deux façons de voir un bloc de
seize petits nombres est portable sur une grande majorité de
trucs, et que dans les deux cas, je peux supposer que le
compilateur saura faire les optimisations qui vont bien ?

tTh.


--
> parce que maintenant linux tue tous les processus pour libérer de la
> mémoire, DONC pas de soucis hein ?
bah, il suffit d'augmenter la mémoire disponible avec
dd if=/dev/zero bs=1024 count=$((1024 * 512)) >> /dev/kcore

10 réponses

1 2
Avatar
JKB
Le 29-05-2008, à propos de
Union de deux tableaux 4x4 et 1x16,
Thierry B. écrivait dans fr.comp.lang.c :

Bonjour le monde.

Question simple, avec un ECM:

-----------------------------------------------
#include <stdio.h>
typedef union
{
char s[4][4];
char l[16];
} machin;
int main(int argc, char *argv[])
{
int x, y, i;
machin m;
/* remplir le machin */
for (i=0; i<16; i++)
m.l[i] = i;
/* afficher le machin */
for (x=0; x<4; x++)
{
for (y=0; y<4; y++)
printf("%2d ", m.s[x][y]);
puts("");
}
return 0;
}
-----------------------------------------------

Ai-je raison de penser que ces deux façons de voir un bloc de
seize petits nombres est portable sur une grande majorité de
trucs, et que dans les deux cas, je peux supposer que le
compilateur saura faire les optimisations qui vont bien ?


À mon avis, c'est assez casse-gueule. Je me souviens de cas où
s[3][4] était vu comme **s (c'était le cas sous Solaris 2.5 avec gcc
2.7.2.3, ça ne nous rajeunit pas...) et non comme un vecteur.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.

Avatar
espie
In article ,
JKB wrote:
Le 29-05-2008, à propos de
Union de deux tableaux 4x4 et 1x16,
Thierry B. écrivait dans fr.comp.lang.c :

Bonjour le monde.

Question simple, avec un ECM:

-----------------------------------------------
#include <stdio.h>
typedef union
{
char s[4][4];
char l[16];
} machin;



Cote representation memoire, ca doit marcher, grace aux calculs habituels
de taille de tableau.

Cote aliasing, ca doit marcher aussi, vu que le type final avec lequel tu
joues est un char.

C'est un tantinet beurk, mais je pense que c'est portable sur toutes
les implementations conformes a la norme, en C89 comme C99...


Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

In article ,
JKB wrote:
Le 29-05-2008, à propos de
Union de deux tableaux 4x4 et 1x16,
Thierry B. écrivait dans fr.comp.lang.c :

Bonjour le monde.

Question simple, avec un ECM:

-----------------------------------------------
#include <stdio.h>
typedef union
{
char s[4][4];
char l[16];
} machin;



Cote representation memoire, ca doit marcher, grace aux calculs habituels
de taille de tableau.

Cote aliasing, ca doit marcher aussi, vu que le type final avec lequel tu
joues est un char.

C'est un tantinet beurk, mais je pense que c'est portable sur toutes
les implementations conformes a la norme, en C89 comme C99...


Une implémentation "validante" qui ajouterait aux unions une donnée
indiquant quel est le dernier membre dans lequel on a écrit et qui lèverait
un signal si on essaie de lire un autre membre (hors X-hack) me semble
conforme et aurait des problèmes.

Quant à savoir ce que peut faire un optimiseur si on lui a appris que c'est
du comportement indéfini et donc qu'il peut déduire que ça ne se passe pas,
je ne me prononcerais pas. Pas sûr que j'aimerais avoir une telle
implémentation, mais si ça permet de gagner 0.0003% sur un des tests de
SPEC, ça se trouvera dans un compilateur.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
candide

C'est un tantinet beurk,


En quoi c'est beurk ?



mais je pense que c'est portable sur toutes
les implementations conformes a la norme, en C89 comme C99...


Donc, on ne serait pas dans ce cas (extrait de C89, §6.3.2.3)

---------------- 8< -------------------------
With one exception, if a member of a union object is accessed after
a value has been stored in a different member of the object, the
behavior is implementation-defined.
---------------- >8 -------------------------

L'exception ne semble pas correspondre à la situation de l'ECM. Par
ailleurs, l'extrait ci-dessus contient une footnote assez compliquée
mais qui module peut-être.

Avatar
Antoine Leca
En news:483ffd95$0$14551$, candide va escriure:

C'est un tantinet beurk,


En quoi c'est beurk ?


Ce n'est pas qosher (strictement conforme si tu préfères).


mais je pense que c'est portable sur toutes
les implementations conformes a la norme, en C89 comme C99...


Donc, on ne serait pas dans ce cas (extrait de C89, §6.3.2.3)
---------------- 8< -------------------------
With one exception, if a member of a union object is accessed after
a value has been stored in a different member of the object, the
behavior is implementation-defined.
---------------- >8 -------------------------


Vous me semblez parler de deux choses différentes.
Marc répond à la question originale, « est-ce que mon truc va marcher sur la
quasi-totalité des implémentations » (dans le texte de la norme, c'est le
sens qu'aurait dû avoir « conforme », s'il était possible de spécifier ce
sens) ; et propose de répondre oui.

Toi, tu te retranches derrière le texte strict de la norme, qui dit que le
comportement dans ce cas est défini par l'implémentation, donc un tel
programme n'est pas strictement conforme (= un peu beurk, = pas qosher, banni de comp.lang.c) ; ce qui est me semble-t-il exact, mais ne me semble
pas être la question originale.

Pour aller plus loin avec le texte que tu cites, comme il s'agit d'une «
implémentation définie » par l'implémentation (donc documentée et devant
respecter les autres règles de la norme, en l'occurence celles sur la
représentation en mémoire des tableaux et la nécessité de continuité),
quelle interprétation proposes-tu pour un hypothétique compilateur («
courrant », ce qui exclut l'hypothèse de Jean-Marc, ou les warnings d'un
splint) qui invaliderait ou même mettrait un bémol sur les hypothèses
originales de Thierry ?


Personnellement, le seul truc qui me chiffonne un peu, c'est si on torture
un peu le bidule avec une architecture de malade genre x86-16 segmentée (et
les pointeurs huge et compagnie), et si on suppose que les tableaux sont
plus grands, en particulier plus grands que 64K, évidemment. Un truc genre

typedef union hugemachin {
char s[6400][16];
char l[102400];
} hugemachin;

Mais même avec des idées tordues dans ce genre, je n'ai pas vu de soucis
avec le code de Thierry, car le fait que ce soit une union va forcer un
compilateur conforme à toujours honorer à la fois les contraintes sur s (qui
doit commencer sur une frontière de 16 octets) et sur l (dont l'arithmétique
doit utiliser les pointeurs huge) ; mais ceci n'est pas contradictoire.


Antoine


Avatar
Thierry B.
--{ Marc Espie a plopé ceci: }--

-----------------------------------------------
#include <stdio.h>
typedef union
{
char s[4][4];
char l[16];
} machin;



Cote representation memoire, ca doit marcher, grace aux calculs habituels
de taille de tableau.


A priori, je n'ai pas trouvé de contre-indications dans les divers
documents que j'ai pu lire.

C'est un tantinet beurk,


Quand au "beurkisme", le vendredi, j'assume...

--
________ http://la.buvette.org/cv.html ________



Avatar
candide

Ce n'est pas qosher (strictement conforme si tu préfères).


D'où ça vient ? Kosher plutôt non ? ( ie "cacher").

Par ailleurs, ce n'est pas comme ça que j'ai compris son "beurk" puisque
M.E. dit que c'est portable sur les implémentations conformes.
Bon en fait tu as raison, il ne dit pas que c'est strictement conforme.
Mais finalement, je viens de comprendre ça, on peut être conforme à la
norme et non portable.



Marc répond à la question originale, « est-ce que mon truc va marcher sur la


Oui mais il ajoute que c'est portable.


Toi, tu te retranches derrière le texte strict de la norme, qui dit que le


Plus ou moins. Je suis un programmeur du dimanche qui cherche un peu la
petite bête mais franchement ce qui est fait dans le code du PO est
contraire à ce que j'avais lu dans la littérature Ctiquement correcte.
Par exemple, Harbison and Steele (éd. 2002, page 163) :

"A component of a union should be referenced only if the last
assignement to the union was through the same component"

(ce qui est repris dans leur § 7.5.4 (Mis)using Union Types, page 165).


Pour aller plus loin avec le texte que tu cites, comme il s'agit
d'une > «implémentation définie » par l'implémentation (donc documentée et


Tiens puisque tu en parles, où (concrètement : quel fichier, quel
paragraphe ?) la fameuse doc fournit-elle les renseignements (extrait du
draft de C ANSI) :


----------------- 8< ----------------------------------
A.6.3 Implementation-defined behavior

Each implementation shall document its behavior in each of the areas
listed in this section. The following are implementation-defined:

----------------- >8 ----------------------------------

Parmi les experts qui fréquentent ce forum, y en aurait-il un qui
pourrait nous copier-coller ce que dit par exemple gcc sur le
comportement défini par l'implémentation de l'ecm du po ?


quelle interprétation proposes-tu pour un hypothétique compilateur («
courrant », ce qui exclut l'hypothèse de Jean-Marc, ou les warnings d'un
splint) qui invaliderait ou même mettrait un bémol sur les hypothèses
originales de Thierry ?


Bon, j'ai pas trop compris quelle "interprétation" tu veux que je
propose. Figure-toi que je cherche pas à savoir comment le compilateur
fait la cuisine, il n'est pour moi qu'une une boite noire censée être
gouvernée par la Norme. En d'autres termes, je m'intéresse aux
interfaces, pas aux implémentations (j'ai déjà eu assez de mal à
comprendre comment fonctionne la dite interface alors s'il faut en plus
connaître les entrailles du compilateur, j'en prends encore pour 10
ans). L'intérêt de la norme est qu'elle me permet d'ignorer pas mal de
choses (ce qui souvent m'arrange).


Personnellement, le seul truc qui me chiffonne un peu, c'est si on torture
un peu le bidule avec une architecture de malade genre x86-16 segmentée (et
les pointeurs huge et compagnie), et si on suppose que les tableaux sont
plus grands, en particulier plus grands que 64K, évidemment. Un truc genre

typedef union hugemachin {
char s[6400][16];
char l[102400];
} hugemachin;

Mais même avec des idées tordues dans ce genre, je n'ai pas vu de soucis
avec le code de Thierry, car le fait que ce soit une union va forcer un
compilateur conforme à toujours honorer à la fois les contraintes sur s (qui
doit commencer sur une frontière de 16 octets) et sur l (dont l'arithmétique
doit utiliser les pointeurs huge) ; mais ceci n'est pas contradictoire.


Je t'avoue que j'ignore complètement et je comprends même pas le
contexte dont tu parles ("architecture genre x86-16 segmentée",
"pointeurs huge", etc) mais j'ai pas compris en quoi le problème dont tu
parles est un problème du aux unions, ça semble être un problème de
tableaux.

Avatar
candide

Parmi les experts qui fréquentent ce forum, y en aurait-il un qui
pourrait nous copier-coller ce que dit par exemple gcc sur le
comportement défini par l'implémentation de l'ecm du po ?





Tiens en fait c'est moins compliqué à trouver que je ne pensais :

----------------------------8<--------------------------------------
4.9 Structures, unions, enumerations, and bit-fields
A member of a union object is accessed using a member of a different
type (C90 6.3.2.3).
The relevant bytes of the representation of the object are treated as an
object of the type used for the access. This may be a trap representation.
---------------------------->8--------------------------------------



Par contre, je n'ai pas vu dans la doc la mention d'un warning ad hoc ?

Avatar
Thierry B.
--{ candide a plopé ceci: }--

----------------------------8<--------------------------------------
4.9 Structures, unions, enumerations, and bit-fields
A member of a union object is accessed using a member of a different
type (C90 6.3.2.3).
The relevant bytes of the representation of the object are treated as an
object of the type used for the access. This may be a trap representation.
---------------------------->8--------------------------------------



Bon, d'un autre coté, comme il me semble bien, d'après ce que j'ai
pu comprendre, qu'un tableau [4][4] serait représenté en mémoire
de la même façon qu'un tableau [16], je pense que mes "relevant
bytes" sont à la bonne place. Pour le moment, ça marche, mais je
n'ai pas essayé avec autre chose que Gcc...

Euh, juste une question idiote: comment traduire "This may be a trap
representation" ?

Par contre, je n'ai pas vu dans la doc la mention d'un warning ad hoc ?


Je pense qu'il doit être assez délicat à implémenter, ce warning.

Encore une fois merci, et je vous tiendrais au courant...

--
Toute machine qui se respecte a sa console sur un port serie... :-)
La question n'est pas de savoir si elle a une console sur port série,

mais de savoir de quelle planète provient le connecteur ;-)
--{ fr.comp.ordinosaures }--

Avatar
Erwan David
"Thierry B." écrivait :


Euh, juste une question idiote: comment traduire "This may be a trap
representation" ?


Une "trap representation" c'est une suite de bits qui ne représente pas
une valeur du type et qui provoque donc une exception si on tente de
l'utiliser. Je ne conaias pas le terme français.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé

1 2