Этот исходный код включает строку в C. Как это сделать?

Я читаю код эмулятора, и я ответил на что-то действительно странное:

switch (reg){
    case 'eax':
    /* and so on*/
}

Как это возможно? Я думал, что вы можете использовать только switch для интегральных типов. Есть ли какие-то макроопределения?

Ответ 1

(Только вы можете ответить на часть макроопределения - если вы не вставляете больше кода. Но здесь не так много макросов для работы - формально вам не разрешено переопределять ключевые слова, поведение при этом - undefined.)

Для обеспечения удобочитаемости программы остроумный разработчик использует поведение, определенное реализацией. 'eax' не строка, а многосимвольная константа. Очень внимательно обратите внимание на одиночные кавычки вокруг eax. Скорее всего, это дает вам int в вашем случае, что уникально для этой комбинации символов. (Довольно часто каждый символ занимает 8 бит в 32 бит int). И все знают, что вы можете switch на int!

Наконец, стандартная ссылка:

В стандарте C99 говорится:

6.4.4.4p10: "Значение целочисленной символьной константы, содержащей более одного символа (например," ab ") или содержащего символ или escape-последовательность, которая не сопоставляется однобайтовому исполнению символ, определяется реализацией".

Ответ 2

В соответствии со стандартом C (6.8.4.2 Оператор switch)

3 Выражение каждой метки случая должно быть целочисленной константой Выражение...

и (6.6 постоянные выражения)

6 Целочисленное константное выражение должно иметь целочисленный тип и должно имеют только операнды, которые являются целыми константами, константами перечисления, символьные константы, sizeof выражения, результаты которых являются целыми константами, и плавающие константы, которые являются непосредственными операндами слепки. Операторы трансляции в целочисленном постоянном выражении должны преобразовывать арифметические типы в целые типы, за исключением как части операнд к оператору sizeof.

Теперь что такое 'eax'?

Стандарт C (6.4.4.4 символьные константы)

2 Целочисленная константа символа последовательность одного или нескольких многобайтные символы, заключенные в одиночные кавычки, как в 'x'...

So 'eax' - целочисленная символьная константа в соответствии с параграфом 10 того же раздела

  1. ... Значение целочисленной символьной константы, содержащей более одного символ (например, "ab" ) или содержащий символ или escape последовательность, которая не сопоставляется однобайтовому символу выполнения, является реализации.

Таким образом, согласно первой упомянутой цитате, он может быть операндом целочисленного постоянного выражения, которое может использоваться как метка case.

Обратите внимание на то, что символьная константа (заключенная в одинарные кавычки) имеет тип int и не совпадает с строковым литералом (последовательность символов, заключенных в двойные кавычки), которая имеет тип массива символов.

Ответ 3

Как говорили другие, это константа int, и ее фактическое значение определяется реализацией.

Я предполагаю, что остальная часть кода выглядит примерно так:

if (SOMETHING)
    reg='eax';
...
switch (reg){
    case 'eax':
    /* and so on*/
}

Вы можете быть уверены, что "eax" в первой части имеет то же значение, что и "eax" во второй части, так что все работает, верно?... неправильно.

В комментарии @Davislor перечислены возможные значения для 'eax':

... 0x65, 0x656178, 0x65617800, 0x786165, 0x6165 или что-то еще

Обратите внимание на первое потенциальное значение? Это просто 'e', игнорируя два других символа. Проблема в том, что программа, вероятно, использует 'eax', 'ebx', и так далее. Если все эти константы имеют то же значение, что и 'e', вы получите

switch (reg){
    case 'e':
       ...
    case 'e':
       ...
    ...
}

Это выглядит не слишком хорошо, не так ли?

Хорошая часть о "реализации" определяется тем, что программист может проверить документацию своего компилятора и посмотреть, делает ли он что-то разумное с этими константами. Если это так, дома бесплатно.

Плохая часть состоит в том, что какой-то другой бедный парень может взять код и попытаться скомпилировать его с помощью другого компилятора. Ошибка мгновенного компиляции. Программа не переносима.

Как заметил в комментариях @zwol, ситуация не так плоха, как я думал, в плохом случае код не компилируется. Это, по крайней мере, даст вам точное имя файла и номер строки для проблемы. Тем не менее, у вас не будет рабочей программы.

Ответ 4

В фрагменте кода используется историческая странность, называемая многосимвольной символьной константой, также называемой многосимволами.

'eax' - целочисленная константа, значение которой определено реализацией.

Вот интересная страница на мульти-символах и их использование, но не должно:

http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html


Оглядываясь назад в зеркало заднего вида, вот как оригинальное руководство от Dennis Ritchie от старых добрых дней (https://www.bell-labs.com/usr/dmr/www/cman.pdf) заданные символьные константы.

2.3.2 Символьные константы

Символьная константа - 1 или 2 символа, заключенных в одинарные кавычки '' '. В пределах символьной константы одиночной кавычки должен предшествовать обратный слэш '' \. Некоторые неграфические символы и сам '< \ могут быть экранированы в соответствии со следующей таблицей:

    BS \b
    NL \n
    CR \r
    HT \t
    ddd \ddd
    \ \\

Побег '' \ddd состоит из обратной косой черты, сопровождаемой 1, 2 или 3 восьмеричными цифрами, которые берутся для указания значения желаемого символа. Частным случаем этой конструкции является "\0 (за которым не следует цифра), которая указывает нулевой символ.

Символьные константы ведут себя точно как целые числа (не, в частности, как объекты типа символа). В соответствии с структурой адресации PDP-11 символьная константа длины 1 имеет код для данного символа в младший байт и 0 в старшем байте; постоянная символа длины 2 имеет код для первого символа в младшем байте и второй символ в старшем байте. Символьные константы с более чем одним символом по своей сути зависят от машины и их следует избегать.

Последняя фраза - это все, что вам нужно запомнить об этой любопытной конструкции: Символьные константы с более чем одним символом по своей сути зависят от машины и их следует избегать.