Dieser source-code ist der Wechsel auf einen string in C. Wie macht es das?
Bin ich beim Lesen über einige emulator-code und ich habe gekontert etwas wirklich sonderbares:
switch (reg){
case 'eax':
/* and so on*/
}
Wie ist das möglich? Ich dachte, Sie könnten nur switch
auf integral-Typen. Gibt es ein paar makro-Tricks Los?
- es ist nicht die Zeichenfolge
'eax'
und es zählt konstanter integer-Wert - Einfache Anführungszeichen, keine doppelten. Eine Zeichenkonstante wird gefördert
int
, so dass es legal ist. Allerdings ist der Wert eines multi-character-Konstante ist durch die Implementierung festgelegt, so dass der code funktioniert möglicherweise nicht wie erwartet auf einem anderen compiler. Zum Beispieleax
sein könnte0x65
,0x656178
,0x65617800
,0x786165
,0x6165
, oder etwas anderes. - der name von der variable "reg", und die Tatsache, dass eax ist ein x86-register, würde ich vermuten, dass die Implementierung-definiert das Verhalten beabsichtigt war OK, denn es ist überall das gleiche, es ist im code verwendet. Nur so lange, wie
'eax' != 'ebx'
natürlich, also es schlägt nur ein oder zwei Ihrer Beispiele. Obwohl es möglicherweise einige code irgendwo, dass in der Tat davon ausgegangen*(int*)("eax") == 'eax'
, und daher schlägt fehl, die meisten Ihrer Beispiele. - Ich don ' T nicht einverstanden mit dem, was Sie sagen, aber es besteht die Reale Gefahr, dass jemand versuchen könnte, um den code zu kompilieren, der auf einem anderen compiler, auch für die gleiche Architektur, und ein anderes Verhalten. Zum Beispiel
'eax'
vielleicht vergleichen Sie gleich'ebx'
oder zu'ax'
, und die switch-Anweisung nicht funktionieren würde, wie gedacht. - Alle, die mystery hätte schnell gebannt, wenn Sie angeschaut hatte bis/uns gezeigt, wie der Datentyp der reg.
- Übrigens, ich würde dazu neigen, betrachten Sie diesen code stinkig. Warum nicht die original-designer definieren Sie eine Enum-Konstante
reg_eax
mit einem nice-Wert, wie null?switch
Aussagen umfasst Sätze von nicht-konsekutive, große Werte nicht kompilieren in schönen Sprung-Tabellen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
(Die nur Sie beantworten können "makro-Tricks" - Teil - es sei denn, Sie fügen mehr code. Aber es gibt nicht viel hier für Makros zu arbeiten - formal sind Sie nicht berechtigt, neu zu definieren keywords; das Verhalten auf, das zu tun ist nicht definiert.)
Zu erreichen, um die Lesbarkeit des Programms, die witzig-Entwickler ist die Nutzung Umsetzung definiert Verhalten.
'eax'
ist nicht ein string, sondern ein multi-character-Konstante. Beachten Sie sehr sorgfältig die einzelnen Anführungszeichen Zeichen umeax
. Wahrscheinlich ist es so dass Sie eineint
in Ihrem Fall, das ist einzigartig in dieser Kombination von Zeichen. (Ziemlich oft jedes Zeichen belegt 8 bit in einem 32-bitint
). Und jeder weiß, Sie könnenswitch
auf eineint
!Schließlich, eine standard-Referenz:
Den C99-standard sagt:
'ab'
aus'a'
und'b'
.'♂'
würde komisch Aussehen.FOURCC('m', 'o', 'o', 'v')
über ein makro. Es ist weniger umständlich, um einfach in der Lage sein zu verwenden'moov'
.Laut C-Standard (6.8.4.2 The switch statement)
und (6.6 Konstante Ausdrücke)
Nun, was ist
'eax'
?C-Standard (6.4.4.4 Zeichenkonstanten)
So
'eax'
ist ein integer, character-Konstante gemäß Absatz 10 von dem gleichen AbschnittAlso nach den ersten erwähnte Zitat, es kann ein operand ein integer-Konstanten Ausdruck kann verwendet werden, als ein Fall label.
Achten, dass eine Zeichen-Konstante (eingeschlossen in Anführungszeichen) hat den Typ
int
und ist nicht das gleiche wie ein string-literal (eine Folge von Zeichen, eingeschlossen in doppelte Anführungszeichen), hat eine Art von ein-Zeichen-array.Wie andere gesagt haben, ist dies ein
int
ständige und der tatsächliche Wert wird durch die Implementierung festgelegt.Ich vermute, der rest des Codes sieht so etwas wie
Können Sie sicher sein, dass 'eax' im ersten Teil hat den gleichen Wert wie 'eax' im zweiten Teil, also es funktioniert alles, richtig? ... falsch.
In einem Kommentar @Davislor listet einige mögliche Werte für 'eax':
Merken, die ersten potenziellen Wert? Das ist nur
'e'
ignorierte die anderen beiden Charaktere. Das problem ist das Programm nutzt wahrscheinlich'eax'
,'ebx'
,und so weiter. Wenn alle diese Konstanten haben den gleichen Wert wie
'e'
Sie am Ende mitDies sieht nicht zu gut, nicht wahr?
Das gute Teil über "implementation-defined" ist, dass kann der Programmierer überprüfen Sie die Dokumentation Ihres Compilers und sehen, ob es etwas vernünftiges mit dieser Konstanten. Wenn Sie es tut, frei Haus.
Der schlechte Teil ist, dass einige Arme Kerl kann den code nehmen und versuchen, zu kompilieren mit einem anderen compiler. Sofortige kompilieren Fehler. Das Programm ist nicht tragbar.
Als @zwol darauf hingewiesen, in den Kommentaren, ist die situation nicht ganz so schlimm, wie ich dachte, im schlechten Fall wird der code nicht kompilieren. Das wird zumindest geben Sie eine genaue Datei name und die Zeilennummer für das problem. Noch, werden Sie nicht haben, ein funktionierendes Programm.
assert('eax' != 'ebx'); //if this fails you can't compile the code because...
ist es etwas, was der ursprüngliche Autor tun können, um zu verhindern, dass andere compiler-Fehler ohne Austausch der völlig konstruieren>Code-fragment verwendet eine historische kuriosität genannt multi-character character constant, auch bezeichnet als multi-chars.
'eax'
eine integer-Konstante, deren Wert wird durch die Implementierung definiert.Hier ist eine interessante Seite, auf multi-chars und wie Sie verwendet werden, sollte aber nicht:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
Suche wieder weiter Weg in den Rückspiegel, hier ist, wie die ursprüngliche C-Handbuch von Dennis Ritchie aus der guten alten Zeit ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) angegebenen Zeichen-Konstanten.
Den letzten Satz ist alles was Sie brauchen, zu erinnern, über diese merkwürdige Konstruktion: Zeichen-Konstanten mit mehr als einem Zeichen sind inhärent Maschine abhängig und sollte vermieden werden.