Я читаю код эмулятора и возражаю против чего-то действительно странного:
switch (reg){
case 'eax':
/* and so on*/
}
Как это возможно? Я думал, что можно только switch
на целочисленных типах. Происходят ли какие-то макросы?
c
switch-statement
label
constants
Ян Колтон
источник
источник
'eax'
и он перечисляет постоянное целочисленное значениеint
, поэтому она разрешена. Однако значение многосимвольной константы определяется реализацией, поэтому код может работать не так, как ожидалось, в другом компиляторе. Например,eax
может быть0x65
,0x656178
,0x65617800
,0x786165
,0x6165
, или что - то еще.'eax' != 'ebx'
, конечно, он не подходит только для одного или двух ваших примеров. Хотя где-то может быть какой-то код, который фактически предполагает*(int*)("eax") == 'eax'
и, следовательно, не работает в большинстве ваших примеров.'eax'
можно сравнить «равно»'ebx'
или «с»'ax'
, и оператор switch не будет работать должным образом.Ответы:
(Только вы можете ответить на вопрос о «обмане с макросами» - если вы не вставите больше кода. Но здесь не так уж много макросов для работы - формально вам не разрешено переопределять ключевые слова ; поведение при выполнении этого не определено.)
Чтобы добиться удобочитаемости программы, остроумный разработчик использует поведение, определяемое реализацией .
'eax'
это не строка, а константа несколько символов . Очень внимательно обратите внимание на одинарные кавычки вокругeax
. Скорее всего,int
в вашем случае это дает вам уникальную комбинацию символов. (Довольно часто каждый символ занимает 8 бит в 32 битеint
). И каждый знает , что вы можетеswitch
наint
!Наконец, стандартная ссылка:
Стандарт C99 гласит:
источник
'ab'
from'a'
и'b'
.Согласно стандарту C (6.8.4.2 оператор switch)
и (6.6 Постоянные выражения)
Что теперь
'eax'
?Стандарт C (6.4.4.4 Символьные константы)
То
'eax'
есть целочисленная символьная константа согласно параграфу 10 того же разделаИтак, согласно первой упомянутой цитате, это может быть операнд целочисленного константного выражения, которое может использоваться как метка case.
Обратите внимание на то, что символьная константа (заключенная в одинарные кавычки) имеет тип
int
и отличается от строкового литерала (последовательность символов, заключенная в двойные кавычки), имеющего тип символьного массива.источник
Как говорили другие, это
int
константа, и ее фактическое значение определяется реализацией.Я предполагаю, что остальная часть кода выглядит примерно так
Вы можете быть уверены, что eax в первой части имеет то же значение, что и eax во второй части, так что все работает, верно? ... неправильно.
В комментарии @Davislor перечисляет некоторые возможные значения для 'eax':
Обратите внимание на первое потенциальное значение? Это просто
'e'
игнорирование двух других персонажей. Проблема в том , программа , вероятно , использует'eax'
,'ebx'
и так далее. Если все эти константы имеют то же значение, что и у'e'
васВыглядит не очень хорошо, правда?
Хорошая особенность «определяемого реализацией» заключается в том, что программист может проверить документацию своего компилятора и посмотреть, делает ли он что-нибудь разумное с этими константами. Если да, то дома бесплатно.
Плохо то, что какой-нибудь другой бедняга может взять код и попытаться скомпилировать его с помощью другого компилятора. Мгновенная ошибка компиляции. Программа не переносима.
Как отметил @zwol в комментариях, ситуация не так плоха, как я думал, в плохом случае код не компилируется. По крайней мере, это даст вам точное имя файла и номер строки проблемы. Все равно у вас не будет работающей программы.
источник
assert('eax' != 'ebx'); //if this fails you can't compile the code because...
может ли оригинальный автор что-нибудь сделать для предотвращения других сбоев компилятора без полной замены конструкции>Во фрагменте кода используется историческая странность, называемая многосимвольной константой , также называемая многосимвольной .
'eax'
- целочисленная константа, значение которой определяется реализацией.Вот интересная страница о нескольких символах и о том, как их можно использовать, но не следует:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
Оглядываясь назад в зеркало заднего вида, вот как в оригинальном руководстве по C Денниса Ритчи из старых добрых времен ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) указаны символьные константы. .
Последняя фраза - это все, что вам нужно запомнить об этой любопытной конструкции: Символьные константы с более чем одним символом по своей сути зависят от машины, и их следует избегать.
источник