Как создать новую строку в макросе cpp?

Как мне написать макрос cpp, который расширяется, чтобы включить переводы строки?

8 ответов

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

Допустим, у нас есть макрос C/C++, который занимает несколько строк, например, в файле с именем MyMacro.hpp.

// Content of MyMacro.hpp

#include "MultilineMacroDebugging.hpp"

#define PRINT_VARIABLE(S) \
__NL__  std::cout << #S << ": " << S << std::endl; \
__NL__  /* more lines if necessary */ \
__NL__  /* even more lines */

В каждый файл, где я определил такой макрос, я включаю другой файл MultilineMacroDebugging.hpp, который содержит следующее:

// Content of MultilineMacroDebugging.hpp

#ifndef HAVE_MULTILINE_DEBUGGING
#define __NL__
#endif

Это определяет пустой макрос __NL__, что делает __NL__ определения исчезают во время предварительной обработки. Затем макрос можно использовать где-нибудь, например, в файле с именем MyImplementation.cpp.

// Content of MyImplementation.cpp

// Uncomment the following line to enable macro debugging
//#define HAVE_MULTILINE_DEBUGGING

#include "MyMacro.hpp"

int a = 10;
PRINT_VARIABLE(a)

Если мне нужно отладить PRINT_VARIABLE макрос, я просто раскомментирую строку, которая определяет макрос HAVE_MULTILINE_DEBUGGING в MyImplementation.cpp. Результирующий код, конечно, не компилируется, так как __NL__ результаты макроса не определены, что приводит к тому, что он остается в скомпилированном коде, но его можно предварительно обработать.

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

Это невозможно. Это было бы уместно, только если вы просматривали список файлов или вывод препроцессора.

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

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

Языки C & C++ одинаково обрабатывают все пробелы вне строк. Просто как разделитель.

Компиляторы C & C++ игнорируют пробельные символы без кавычек (за исключением проблемы с шаблоном> >), поэтому получение макроса для запуска новых строк не имеет смысла. Вы можете создать макрос на несколько строк, оканчивая каждую строку макроса обратной косой чертой, но это не выводит символы новой строки.

Компилятор C знает о пробеле, но он не различает пробелы, табуляции или новые строки.

Если вы имеете в виду, как у меня есть новая строка внутри макроса, то:

#define SOME_STRING "Some string\n with a new line."

буду работать.

У меня та же проблема. Я злоупотребляю препроцессором в файлах, отличных от C, поэтому тот факт, что компилятор C игнорирует разрывы строк, для меня не имеет значения. Я использую \\ в конце строк в определении макроса (это довольно аккуратный синтаксис, напоминающий LaTeX) и передаю результат через

      sed s/'\\ '/'\n'/g

Это помогает. Препроцессор отделяет один \ от \\ и соединяет строки, а sed снова разделяет их, заменяя оставшийся \ реальным символом новой строки.

Не совсем уверен, что вы спрашиваете здесь. Хотите макрос на несколько строк?

#define NEWLINE_MACRO(x) line1 \
line2 \
line3

Кроме того, если вы хотите включить литерал в ваш макрос:

#define NEWLINE_MACRO(x) ##x

то, что вы положили в x, будет помещено вместо ##x, поэтому:

NEWLINE_MACRO( line1 ) // is replaced with line1

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

Также:

#define NEWLINE_MACRO(x) #x // stringify x

Поставит кавычки вокруг х

Использование \, вот так:

#define my_multiline_macro(a, b, c) \
if (a) { \
    b += c; \
}

Используйте \ в конце строки. Я видел много макросов C, где они используют do...while(0)

#define foo() do \
{
  //code goes here \
  \
  \
}while(0);

Кроме того, не забывайте использовать скобки во многих случаях.

Пример:

#define foo(x) a+b
//should be
#define foo(x) (a+b)
Другие вопросы по тегам