Je lis un code d'émulateur et j'ai contré quelque chose de vraiment étrange:
switch (reg){
case 'eax':
/* and so on*/
}
Comment est-ce possible? Je pensais que vous ne pouviez que switch
sur les types intégraux. Y a-t-il des tromperies macro?
c
switch-statement
label
constants
Ian Colton
la source
la source
'eax'
et elle énumère la valeur entière constanteint
, donc c'est légal. Cependant, la valeur d'une constante à plusieurs caractères est définie par l'implémentation, de sorte que le code peut ne pas fonctionner comme prévu sur un autre compilateur. Par exemple,eax
peut - être0x65
,0x656178
,0x65617800
,0x786165
,0x6165
, ou autre chose.'eax' != 'ebx'
, bien sûr, cela ne fait échouer qu'un ou deux de vos exemples. Bien qu'il puisse y avoir du code quelque part qui en fait suppose*(int*)("eax") == 'eax'
, et donc échoue la plupart de vos exemples.'eax'
pourrait comparer égal à'ebx'
ou à'ax'
, et l'instruction switch ne fonctionnerait pas comme prévu.Réponses:
(Vous seul pouvez répondre à la partie "macros tricherie" - à moins que vous ne colliez plus de code. Mais il n'y a pas grand-chose ici pour les macros sur lesquelles travailler - formellement, vous n'êtes pas autorisé à redéfinir les mots-clés ; le comportement en ce sens n'est pas défini.)
Afin d'atteindre la lisibilité du programme, le développeur intelligent exploite le comportement défini par l'implémentation .
'eax'
n'est pas une chaîne, mais une constante à plusieurs caractères . Notez très attentivement les caractères de guillemets simples autoureax
. Très probablement, cela vous donne unint
dans votre cas qui est unique à cette combinaison de caractères. (Assez souvent, chaque caractère occupe 8 bits dans un 32 bitsint
). Et tout le monde sait que vous pouvezswitch
sur unint
!Enfin, une référence standard:
La norme C99 dit:
la source
'ab'
from'a'
et'b'
.Selon la norme C (6.8.4.2 L'instruction switch)
et (6.6 Expressions constantes)
Maintenant qu'est-ce que c'est
'eax'
?La norme C (6.4.4.4 Constantes de caractères)
Ainsi
'eax'
est une constante de caractère entier selon le paragraphe 10 de la même sectionAinsi, selon la première citation mentionnée, il peut s'agir d'un opérande d'une expression constante entière qui peut être utilisée comme étiquette de cas.
Faites attention au fait qu'une constante de caractère (entre guillemets simples) a un type
int
et n'est pas la même chose qu'une chaîne littérale (une séquence de caractères entre guillemets) qui a un type de tableau de caractères.la source
Comme d'autres l'ont dit, il s'agit d'une
int
constante et sa valeur réelle est définie par l'implémentation.Je suppose que le reste du code ressemble à quelque chose comme
Vous pouvez être sûr que «eax» dans la première partie a la même valeur que «eax» dans la deuxième partie, donc tout fonctionne, non? ... faux.
Dans un commentaire, @Davislor énumère quelques valeurs possibles pour 'eax':
Remarquez la première valeur potentielle? C'est juste
'e'
, en ignorant les deux autres personnages. Le problème est le programme utilise probablement'eax'
,'ebx'
et ainsi de suite. Si toutes ces constantes ont la même valeur que'e'
vous vous retrouvez avecCela n'a pas l'air trop beau, n'est-ce pas?
La bonne partie de "défini par l'implémentation" est que le programmeur peut vérifier la documentation de son compilateur et voir s'il fait quelque chose de sensé avec ces constantes. Si c'est le cas, gratuitement à la maison.
La mauvaise partie est qu'un autre pauvre type peut prendre le code et essayer de le compiler en utilisant un autre compilateur. Erreur de compilation instantanée. Le programme n'est pas portable.
Comme @zwol l'a souligné dans les commentaires, la situation n'est pas aussi mauvaise que je le pensais, dans le mauvais cas, le code ne se compile pas. Cela vous donnera au moins un nom de fichier et un numéro de ligne exacts pour le problème. Pourtant, vous n'aurez pas de programme de travail.
la source
assert('eax' != 'ebx'); //if this fails you can't compile the code because...
y a-t-il quelque chose que l'auteur original pourrait faire pour empêcher d'autres échecs du compilateur sans remplacer entièrement la construction>Le fragment de code utilise une bizarrerie historique appelée constante de caractère multi-caractères , également appelée multi-caractères .
'eax'
est une constante entière dont la valeur est définie par l'implémentation.Voici une page intéressante sur les multi-caractères et comment ils peuvent être utilisés mais ne devraient pas:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
En regardant en arrière plus loin dans le rétroviseur, voici comment le manuel C original de Dennis Ritchie du bon vieux temps ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) spécifiait les constantes de caractères .
La dernière phrase est tout ce dont vous devez vous souvenir à propos de cette curieuse construction: les constantes de caractère avec plus d'un caractère sont intrinsèquement dépendantes de la machine et doivent être évitées.
la source