Ответ 1
Конкатенация смежных строк litterals не является особенностью препроцессора, это особенность основных языков (как C, так и С++). Вы можете написать:
printf("Hello "
" world\n");
Можно ли объединить строки во время предварительной обработки?
Я нашел этот пример
#define H "Hello "
#define W "World!"
#define HW H W
printf(HW); // Prints "Hello World!"
Однако это не работает для меня - выводит "Привет", когда я использую gcc -std=c99
UPD Этот пример выглядит как работающий сейчас. Однако, это обычная функция препроцессора c?
Конкатенация смежных строк litterals не является особенностью препроцессора, это особенность основных языков (как C, так и С++). Вы можете написать:
printf("Hello "
" world\n");
Вы можете объединить токены в препроцессоре, но будьте осторожны, потому что это сложно. Ключ - это оператор ##. Если бы вы выбрали это в верхней части кода:
#define myexample(x,y,z) int example_##x##_##y##_##z## = x##y##z
то в основном, что это делает, заключается в том, что во время предварительной обработки он будет принимать любой вызов этого макроса, например:
myexample(1,2,3);
и он буквально превратится в
int example_1_2_3 = 123;
Это позволяет вам обладать гибкостью при кодировании, если вы используете его правильно, но это не совсем верно, как вы пытаетесь его использовать. С небольшим массажем вы можете заставить его работать, хотя.
Одним из возможных решений для вашего примера может быть:
#define H "Hello "
#define W "World!"
#define concat_and_print(a, b) cout << a << b << endl
а затем сделайте что-то вроде
concat_and_print(H,W);
Из gcc online docs:
Оператор предварительной обработки '##' выполняет вставку маркера. Когда макрос расширяется, два токена по обе стороны каждого оператора "##" объединены в один токен, который затем заменяет "##" и два оригинальных токена в расширении макроса.
Рассмотрим программу на языке C, которая интерпретирует именованные команды. Вероятно, должна быть таблица команд, возможно, массив структур, объявленный следующим образом:
struct command { char *name; void (*function) (void); }; struct command commands[] = { { "quit", quit_command }, { "help", help_command }, ... };
Было бы проще не указывать имя каждой команды дважды, один раз в строковой константе и один раз в имени функции. Макрос, который принимает имя команды в качестве аргумента, может сделать это ненужным. Строковая константа может быть создана с помощью строкования и имя функции, объединяя аргумент с помощью
_command
. Вот как это делается:#define COMMAND(NAME) { #NAME, NAME ## _command } struct command commands[] = { COMMAND (quit), COMMAND (help), ... };
Я просто подумал, что добавлю ответ, который ссылается на источник, почему это работает.
Стандарт C99 §5.1.1.2 определяет фазы перевода кода C. В подразделе 6 говорится:
- Связанные токены строковых литералов конкатенированы.
Аналогично, в стандартах С++ (ISO 14882) в § 2.1 определяются этапы перевода. Здесь в подразделе 6 говорится:
6 Смежные обычные строковые литералы связаны друг с другом. Смежные широкоформатные литеральные жетоны конкатенированы.
Вот почему вы можете конкатенировать строки просто, смещая их друг с другом:
printf("string"" one\n");
>> ./a.out
>> string one
Предпроцессорная часть вопроса - это просто использование директивы #define
preprocessing, которая выполняет подстановку из идентификатора (H
) в строку ("Hello "
).