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

Variable de type enumeration

63 réponses
Avatar
candide
Bonjour,

La norme C90 dit

--------------------------- 8< ------------------------------------
Each enumerated type shall be compatible with an integer type; the
choice of type is implementation-defined.
--------------------------- >8 ------------------------------------

Ce qui n'est pas très clair c'est que par ailleurs :

--------------------------- 8< ------------------------------------
An identifier declared as an enumeration constant has type int.
--------------------------- >8 ------------------------------------

Je me pose donc la question de savoir si on peut utiliser sans risque
une variable de type énumération exactement comme s'il s'agissait d'une
variable de type int ? Je dis "sans risque" parce que formellement, je
crois que rien ne m'en empêche :

--------------------------- 8< ------------------------------------
A char, a short int, or an int bit-field, or their signed or
unsigned varieties, or an object that has enumeration type, may be
used in an expression wherever an int or unsigned int may be used.
--------------------------- >8 ------------------------------------

Si, par exemple

enum toto {A=34, B=51} t;

peut-on écrire

t=28;

(cela pourrait poser problème si l'on considère que les valeurs prises
par une variable de type enum toto sont parmi 34 et 51, cf. ma première
citation de la norme) ? Bon, en fait j'imagine que ça ne pose pas de
problème particulier mais je trouve que la norme n'est pas formelle sur
ce point. Par contre, pourrait-il y avoir des problèmes si on écrivait

t=-5;

?

Quelles précautions particulières prendre avec des variables de type
énumération ? Harbison & Steele recommandent une certaine prudence :


--------------------------- 8< ------------------------------------
We suggest that programmers treat enumerated types as different from
integers and not mix them in integer expressions without using casts.
--------------------------- >8 ------------------------------------

mais ils ne donnent aucun exemple illustrant les précautions à prendre.
Concrètement faut faire quoi ? Ainsi dans mon premier exemple ci-dessus,
dois-je écrire

t=(enum toto) 28;

?

Merci.

10 réponses

3 4 5 6 7
Avatar
Pierre Maurette
Wykaaa, le 07/07/2008 a écrit :

[...]

Dans le compilateur C que nous avions fait, le switch générait un tableau de
branchement ce qui évitait de générer des tests pour se brancher. Sur la
machine cible, on disposait d'une instruction assembleur de branchement avec
adressage indexé.



[...]

Il est clair que, du coup, les 2 algos ne sont pas les mêmes...



Ce n'est pas ce que je voulais dire. On se fiche du code généré et des
éventuelles libertés prises par le compilateur. Les deux algorithmes ne
sont pas les mêmes dans le code source.

--
Pierre Maurette
Avatar
espie
In article ,
Pierre Maurette wrote:
Le switch...case est un branchement selon valeur. Il peut être sans
test et à nombre de cycles constant quelque soit l'aiguillage. Ceci
d'autant plus facilement qu'on utilise l'enum en bon père de famille,
c'est à dire en laissant le compilateur affecter les valeurs de 0 à N,
et pourquoi pas en type compatible avec une adresse ou un offset. Je
vous fais grâce de la structure du code machine que j'ai en tête, c'est
évident. Je dois avouer que sur un seul essai trop rapide et avec juste
une paire de cas, je n'ai pas mis ce truc en évidence. Mais il faudrait
refaire soigneusement des essais, avec plusieurs compilateurs et
surtout un aiguillage sur quelques centaines de messages.

A l'opposé, dans un aiguillage par un if...else if...else if...else,
vous imposez un ordre de traitement. Ça permet de hiérarchiser, et donc
de traiter "deux fois la même valeur". Ça peut être intéressant si on a
un cas qui se présente statistiquement "presque toujours". Si bien sûr
on en tient compte, ce qui est quand même la moindre des choses.



Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.
Avatar
Pierre Maurette
Marc Espie, le 07/07/2008 a écrit :

[...]

Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.



Je ne sais pas trop jusqu'où il peut aller. Mais si j'écris:

if cond1
...
else if cond2
...

.......

else if condN
...
else
...

ça me ferait un peu mal au derche qu'il s'autorise à ne pas faire les
tests dans l'ordre, et ce sans user du volatile. D'autant que sauf
erreur de ma part l'évaluation de la condition sous un if (ah... la
campagne...) est un point de séquence. Comme celle d'un switch, d'un
while, les trois membres d'un for.

--
Pierre Maurette
Avatar
Pierre Maurette
(supersedes )

Marc Espie, le 07/07/2008 a écrit :

[...]

Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.



Je ne sais pas trop jusqu'où il peut aller. Mais si j'écris:

if cond1
...
else if cond2
...

.......

else if condN
...
else
...

ça me ferait un peu mal au derche qu'il s'autorise à ne pas faire les
tests dans l'ordre, et ce sans user du volatile. D'autant que sauf
erreur de ma part l'évaluation de la condition sous un if (ah... la
campagne...) est un point de séquence. Comme celle d'un switch, d'un
while, les trois membres d'un for.

Ajout: à moins qu'il n'y ait des options spécifique, comme celle qui
gère le développement en dur des boucles courtes. Intel ? C'est
vachenemnt pratique, d'ailleurs.

--
Pierre Maurette
Avatar
espie
In article ,
Pierre Maurette wrote:
(supersedes )

Marc Espie, le 07/07/2008 a écrit :

[...]

Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.



Je ne sais pas trop jusqu'où il peut aller. Mais si j'écris:

if cond1
...
else if cond2
...

.......

else if condN
...
else
...

ça me ferait un peu mal au derche qu'il s'autorise à ne pas faire les
tests dans l'ordre, et ce sans user du volatile. D'autant que sauf
erreur de ma part l'évaluation de la condition sous un if (ah... la
campagne...) est un point de séquence. Comme celle d'un switch, d'un
while, les trois membres d'un for.



Si c'est des tests simples, du style

if (var == constante)
else if (var == constante2)
else if (var == constante3)

j'espere bien qu'il va se rendre compte que c'est de la meme variable
qu'il s'agit, et qu'il va s'autoriser a faire les choses dans le
desordre !

La moindre des choses qu'on attend d'un compilo moderne, c'est bien qu'il
sache reperer les operations sans effets de bord et qu'il peut permuter.

Sinon, tu peux courir pour avoir un semblant de performance sur a peu
pres n'importe quoi de moderne, la plupart des procs recents ayant la
capacite de paralleliser des calculs sur leurs plusieurs unites arithmetiques,
a condition que ceux-ci soient independants...
Avatar
Wykaaa
Pierre Maurette a écrit :
Wykaaa, le 07/07/2008 a écrit :

[...]

Dans le compilateur C que nous avions fait, le switch générait un
tableau de branchement ce qui évitait de générer des tests pour se
brancher. Sur la machine cible, on disposait d'une instruction
assembleur de branchement avec adressage indexé.



[...]

Il est clair que, du coup, les 2 algos ne sont pas les mêmes...



Ce n'est pas ce que je voulais dire. On se fiche du code généré et des
éventuelles libertés prises par le compilateur. Les deux algorithmes ne
sont pas les mêmes dans le code source.



Excuse-moi, je croyais que tu parlais du généré.
Avatar
Wykaaa
Marc Espie a écrit :
In article ,
Pierre Maurette wrote:
(supersedes )

Marc Espie, le 07/07/2008 a écrit :

[...]

Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.


Je ne sais pas trop jusqu'où il peut aller. Mais si j'écris:

if cond1
...
else if cond2
...

.......

else if condN
...
else
...

ça me ferait un peu mal au derche qu'il s'autorise à ne pas faire les
tests dans l'ordre, et ce sans user du volatile. D'autant que sauf
erreur de ma part l'évaluation de la condition sous un if (ah... la
campagne...) est un point de séquence. Comme celle d'un switch, d'un
while, les trois membres d'un for.



Si c'est des tests simples, du style

if (var == constante)
else if (var == constante2)
else if (var == constante3)

j'espere bien qu'il va se rendre compte que c'est de la meme variable
qu'il s'agit, et qu'il va s'autoriser a faire les choses dans le
desordre !



Et bien non !
Moi je ne veux pas qu'il me réorganise un tel code si j'ai mis les cas
les plus fréquents d'abord !!

La moindre des choses qu'on attend d'un compilo moderne, c'est bien qu'il
sache reperer les operations sans effets de bord et qu'il peut permuter.



Non et non. Ou alors je veux des options (au niveau d'une expression ou
d'une instruction, pas au niveau du compilo) )qui permettent de lui dire
que je ne veux pas qu'il permute

Sinon, tu peux courir pour avoir un semblant de performance sur a peu
pres n'importe quoi de moderne, la plupart des procs recents ayant la
capacite de paralleliser des calculs sur leurs plusieurs unites arithmetiques,
a condition que ceux-ci soient independants...



Oui, bof, on en dit plus qu'ils n'en font, en général...
Avatar
espie
In article <48724f0c$0$911$,
Wykaaa wrote:
Marc Espie a écrit :
In article ,
Pierre Maurette wrote:
(supersedes )

Marc Espie, le 07/07/2008 a écrit :

[...]

Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.


Je ne sais pas trop jusqu'où il peut aller. Mais si j'écris:

if cond1
...
else if cond2
...

.......

else if condN
...
else
...

ça me ferait un peu mal au derche qu'il s'autorise à ne pas faire les
tests dans l'ordre, et ce sans user du volatile. D'autant que sauf
erreur de ma part l'évaluation de la condition sous un if (ah... la
campagne...) est un point de séquence. Comme celle d'un switch, d'un
while, les trois membres d'un for.



Si c'est des tests simples, du style

if (var == constante)
else if (var == constante2)
else if (var == constante3)

j'espere bien qu'il va se rendre compte que c'est de la meme variable
qu'il s'agit, et qu'il va s'autoriser a faire les choses dans le
desordre !



Et bien non !
Moi je ne veux pas qu'il me réorganise un tel code si j'ai mis les cas
les plus fréquents d'abord !!



C'est a ca que servent les profilers et les profile-directed optimizations,
hein...

La moindre des choses qu'on attend d'un compilo moderne, c'est bien qu'il
sache reperer les operations sans effets de bord et qu'il peut permuter.



Non et non. Ou alors je veux des options (au niveau d'une expression ou
d'une instruction, pas au niveau du compilo) )qui permettent de lui dire
que je ne veux pas qu'il permute



L'ordre d'evaluation des expressions, en l'absence de volatile, ne fait
pas partie des comportements observables -> tant que le resultat est
le meme, ton compilo a parfaitement le droit de tout reordonner. Le reste
est affaire de qualite du compilateur. Moi j'attend de lui qu'il reordonne
si le resultat va plus vite, et qu'il laisse en l'etat sinon, sauf si je
lui demande d'optimiser pour la taille et pas pour la vitesse.

Si tu veux un comportement plus specifique, passe a l'assembleur, ou reste
avec un compilo des annees '80...
Avatar
Wykaaa
Marc Espie a écrit :
In article <48724f0c$0$911$,
Wykaaa wrote:
Marc Espie a écrit :
In article ,
Pierre Maurette wrote:
(supersedes )

Marc Espie, le 07/07/2008 a écrit :

[...]

Faut pas que deconner non plus, tout compilo vaguement moderne sait
refabriquer un goto a partir d'une serie de if.


Je ne sais pas trop jusqu'où il peut aller. Mais si j'écris:

if cond1
...
else if cond2
...

.......

else if condN
...
else
...

ça me ferait un peu mal au derche qu'il s'autorise à ne pas faire les
tests dans l'ordre, et ce sans user du volatile. D'autant que sauf
erreur de ma part l'évaluation de la condition sous un if (ah... la
campagne...) est un point de séquence. Comme celle d'un switch, d'un
while, les trois membres d'un for.


Si c'est des tests simples, du style

if (var == constante)
else if (var == constante2)
else if (var == constante3)

j'espere bien qu'il va se rendre compte que c'est de la meme variable
qu'il s'agit, et qu'il va s'autoriser a faire les choses dans le
desordre !


Et bien non !
Moi je ne veux pas qu'il me réorganise un tel code si j'ai mis les cas
les plus fréquents d'abord !!



C'est a ca que servent les profilers et les profile-directed optimizations,
hein...

La moindre des choses qu'on attend d'un compilo moderne, c'est bien qu'il
sache reperer les operations sans effets de bord et qu'il peut permuter.


Non et non. Ou alors je veux des options (au niveau d'une expression ou
d'une instruction, pas au niveau du compilo) )qui permettent de lui dire
que je ne veux pas qu'il permute



L'ordre d'evaluation des expressions, en l'absence de volatile, ne fait
pas partie des comportements observables -> tant que le resultat est
le meme, ton compilo a parfaitement le droit de tout reordonner. Le reste
est affaire de qualite du compilateur. Moi j'attend de lui qu'il reordonne
si le resultat va plus vite, et qu'il laisse en l'etat sinon, sauf si je
lui demande d'optimiser pour la taille et pas pour la vitesse.

Si tu veux un comportement plus specifique, passe a l'assembleur, ou reste
avec un compilo des annees '80...



J'ai fait un optimiseur pour les calculs flottants dans un compilo
Fortran (dans les années 80) et malgré tout ce que l'on peut dire, ce
n'est jamais à sémantique strictement équivalente à cause, entre autre,
des over et underflows.
Je me suis d'ailleurs fait prendre, dans les années 70, par le compilo
Fortran IV étendu d'IBM qui, à cause d'une optimisation (permutation
dans une expression) a fait qu'à l'exécution, j'ai eu un abort à cause
d'un logarithme négatif, ce qui n'aurait jamais dû se produire.
J'ai dû recompiler mon programme en débrayant toute optimisation pour
que mon programme fasse réellement ce que j'attendais de lui.
Avatar
espie
In article <48725ad4$0$883$,
Wykaaa wrote:
Si tu veux un comportement plus specifique, passe a l'assembleur, ou reste
avec un compilo des annees '80...



J'ai fait un optimiseur pour les calculs flottants dans un compilo
Fortran (dans les années 80) et malgré tout ce que l'on peut dire, ce
n'est jamais à sémantique strictement équivalente à cause, entre autre,
des over et underflows.



Merci de comparer ce qui est comparable... l'optimisation sur les calculs
flottants, c'est connu, est nettement plus complexe et tordue que sur les
entiers... et encore pire sur i386, avec les registres qui sont plus grands
que la memoire... mais meme sur d'autres archis, c'est parfois rigolo,
confere l'alpha et ses barrieres necessaires pour recuperer les divisions
par zero, un jour ou l'autre.

Je me suis d'ailleurs fait prendre, dans les années 70, par le compilo
Fortran IV étendu d'IBM qui, à cause d'une optimisation (permutation
dans une expression) a fait qu'à l'exécution, j'ai eu un abort à cause
d'un logarithme négatif, ce qui n'aurait jamais dû se produire.



C'est evidemment une erreur du compilateur.

J'ai dû recompiler mon programme en débrayant toute optimisation pour
que mon programme fasse réellement ce que j'attendais de lui.


3 4 5 6 7