Ich lese einen Emulatorcode durch und habe etwas wirklich Seltsames kontert:
switch (reg){
case 'eax':
/* and so on*/
}
Wie ist das möglich? Ich dachte man könnte nur switch
auf ganzzahlige Typen. Gibt es Makrotricks?
c
switch-statement
label
constants
Ian Colton
quelle
quelle
'eax'
und es zählt konstanten ganzzahligen Wert aufint
, daher ist dies legal. Der Wert einer Konstante mit mehreren Zeichen ist jedoch implementierungsdefiniert, sodass der Code auf einem anderen Compiler möglicherweise nicht wie erwartet funktioniert. Zum Beispieleax
könnte sein0x65
,0x656178
,0x65617800
,0x786165
,0x6165
, oder etwas anderes.'eax' != 'ebx'
natürlich, so scheitert es nur an einem oder zwei Ihrer Beispiele. Obwohl es möglicherweise irgendwo Code gibt, der tatsächlich davon ausgeht*(int*)("eax") == 'eax'
und daher die meisten Ihrer Beispiele fehlschlägt.'eax'
könnte ein Vergleich gleich'ebx'
oder gleich sein'ax'
, und die switch-Anweisung würde nicht wie beabsichtigt funktionieren.Antworten:
(Nur Sie können den Teil "Makro-Tricks" beantworten - es sei denn, Sie fügen mehr Code ein. Es gibt hier jedoch nicht viel, woran Makros arbeiten können. Formal dürfen Sie Schlüsselwörter nicht neu definieren . Das Verhalten dabei ist undefiniert.)
Um die Programmlesbarkeit zu erreichen, nutzt der witzige Entwickler das implementierungsdefinierte Verhalten .
'eax'
ist keine Zeichenfolge, sondern eine Konstante mit mehreren Zeichen . Beachten Sie die einzelnen Anführungszeichen sehr sorgfältigeax
. Höchstwahrscheinlich gibt es Ihnenint
in Ihrem Fall eine, die für diese Kombination von Zeichen einzigartig ist. (Sehr oft belegt jedes Zeichen 8 Bit in 32 Bitint
). Und jeder weiß, dass Sieswitch
auf einem könnenint
!Zum Schluss noch eine Standardreferenz:
Der C99-Standard sagt:
quelle
'ab'
from'a'
und zu berechnen'b'
.Nach dem C-Standard (6.8.4.2 Die switch-Anweisung)
und (6.6 Konstante Ausdrücke)
Was ist nun?
'eax'
?Der C-Standard (6.4.4.4 Zeichenkonstanten)
So
'eax'
ist eine ganzzahlige Zeichenkonstante gemäß Absatz 10 desselben AbschnittsNach dem erstgenannten Zitat kann es sich also um einen Operanden eines ganzzahligen konstanten Ausdrucks handeln, der als Fallbezeichnung verwendet werden kann.
Beachten Sie, dass eine Zeichenkonstante (in einfache Anführungszeichen eingeschlossen) vom Typ ist
int
und nicht mit einem Zeichenfolgenliteral (einer Folge von Zeichen in doppelten Anführungszeichen) identisch ist, das den Typ eines Zeichenarrays hat.quelle
Wie andere gesagt haben, ist dies ein
int
Konstante und ihr tatsächlicher Wert ist implementierungsdefiniert.Ich gehe davon aus, dass der Rest des Codes ungefähr so aussieht
Sie können sicher sein, dass 'eax' im ersten Teil den gleichen Wert wie 'eax' im zweiten Teil hat, also klappt alles, oder? ... falsch.
In einem Kommentar listet @Davislor einige mögliche Werte für 'eax' auf:
Beachten Sie den ersten möglichen Wert? Das heißt
'e'
, die beiden anderen Zeichen werden ignoriert. Das Problem ist das Programm wahrscheinlich verwendet'eax'
,'ebx'
und so weiter. Wenn alle diese Konstanten den gleichen Wert haben, den'e'
Sie am Ende habenDas sieht doch nicht gut aus, oder?
Das Gute an "implementierungsdefiniert" ist, dass der Programmierer die Dokumentation seines Compilers überprüfen kann, um festzustellen, ob er mit diesen Konstanten etwas Sinnvolles macht. Wenn ja, frei zu Hause.
Das Schlimme ist, dass ein anderer armer Kerl den Code nehmen und versuchen kann, ihn mit einem anderen Compiler zu kompilieren. Sofortiger Kompilierungsfehler. Das Programm ist nicht portierbar.
Wie @zwol in den Kommentaren betonte, ist die Situation nicht ganz so schlimm wie ich dachte, im schlimmsten Fall wird der Code nicht kompiliert. Dadurch erhalten Sie mindestens einen genauen Dateinamen und eine Zeilennummer für das Problem. Trotzdem haben Sie kein Arbeitsprogramm.
quelle
assert('eax' != 'ebx'); //if this fails you can't compile the code because...
gibt es irgendetwas, was der ursprüngliche Autor tun könnte, um andere Compilerfehler zu verhindern, ohne das Konstrukt vollständig zu ersetzen.Das Codefragment verwendet eine historische Kuriosität, die als Zeichenkonstante mit mehreren Zeichen bezeichnet wird und auch als Zeichen mit mehreren Zeichen bezeichnet wird .
'eax'
ist eine ganzzahlige Konstante, deren Wert durch die Implementierung definiert ist.Hier ist eine interessante Seite über Multi-Zeichen und wie sie verwendet werden können, aber nicht sollten:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
Wenn Sie weiter in den Rückspiegel zurückblicken, finden Sie im Original-C-Handbuch von Dennis Ritchie aus guten alten Zeiten ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) Zeichenkonstanten .
Der letzte Satz ist alles, woran Sie sich bei dieser merkwürdigen Konstruktion erinnern müssen: Zeichenkonstanten mit mehr als einem Zeichen sind von Natur aus maschinenabhängig und sollten vermieden werden.
quelle