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

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


person user18458    schedule 19.09.2008    source источник
comment
Вы можете объяснить, почему вы хотите это сделать?   -  person Lou Franco    schedule 19.09.2008
comment
@LouFranco, наверное, чтобы было удобнее читать?   -  person Erel Segal-Halevi    schedule 19.01.2014
comment
Глядя на ответы ниже, становится ясно, что вы не можете. Принимая это во внимание, проблема может заключаться в следующем: «Ура, делаешь это ронг». Лучшее решение для вас (и наиболее распространенное при использовании макросов C) может заключаться в том, чтобы макрос просто выполнял минимальную работу, которую он может, а затем передавал большую часть работы вспомогательной функции. Сила макросов + функциональный красиво отформатированный код C в неоптимизированных сборках = win win.   -  person Slipp D. Thompson    schedule 14.07.2014
comment
Это возможный дубликат Как сделать G ++ препроцессор выводит новую строку в макросе? Хотя другой вопрос более конкретен, у него есть хорошие ответы, охватывающие все, что здесь задают.   -  person Kuba hasn't forgotten Monica    schedule 12.08.2014
comment
Для языков, в которых есть значимые пробелы (например, haskell с GHC), не редкость использовать препроцессор C для констант и расширения макросов. Он также используется gcc при обработке файлов сборки (если расширение .S). Итак, это три варианта использования fwiw   -  person jberryman    schedule 26.12.2016
comment
Это было бы очень полезно для макросов, которые должны создавать #pragmas в развернутом теле. (случай под рукой OpenMP)   -  person NoahR    schedule 04.04.2017
comment
Я отправляю результат cpp в clang-format. Теперь получаю читаемый результат.   -  person Jean-Bernard Jansen    schedule 28.04.2017
comment
Может быть актуально: Предварительная обработка с использованием m4 и Замены препроцессора C. (Мне действительно нужно что-то, чтобы добавить новые строки, чтобы я мог распутать макросы).   -  person jww    schedule 02.07.2018


Ответы (7)


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

Допустим, у нас есть макрос 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__ undefined, что заставляет его оставаться в скомпилированном коде, но его можно, однако, предварительно обработать.

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

person Florian Fleissner    schedule 03.04.2016
comment
Google всегда приводит меня сюда. Итак, для меня и всех остальных я нашел онлайн-инструмент, который помогает реструктурировать вывод макросов: codebeautify. org / c-formatter-beautifier - person Henrik; 15.11.2019

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

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

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

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

person itj    schedule 19.09.2008
comment
Это было бы актуально только в том случае, если вы просматривали список файлов или вывод препроцессора. В этом был весь смысл вопроса :) - person Kuba hasn't forgotten Monica; 12.08.2014
comment
К вашему сведению: я пытаюсь сгенерировать несколько строк сборки в файле .S из макроса .... Увы, ассемблер НЕ позволяет использовать несколько операторов в строке. - person rew; 22.10.2020

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

person Mike Thompson    schedule 19.09.2008
comment
На самом деле это имеет смысл, если вы хотите проверить предварительно обработанный код. Тогда новые строки помогут оценить его правильность для целей отладки. - person monkeydom; 05.10.2013
comment
Почему этот ответ получил положительные голоса? Это не отвечает на вопрос. - person David Baird; 03.05.2014
comment
@DavidBaird Ditto. Ответ на самом деле не отвечает на вопрос. - person bddicken; 30.05.2014
comment
@ bddicken: Моя ситуация - это то, что сказал monkeydom, и это действительно имеет смысл! - person David Baird; 04.06.2014
comment
@DavidBaird @ bddicken: Я думаю, из ответа довольно легко вытекает, что «вы не можете», даже если автор не сказал этого прямо. И глядя на другие ответы, кажется, что это правда - нет способа сделать это, извините, нет. Учитывая это, этот ответ является одним из самых коротких и кратких, подтверждающих правильность конструкции системы, и является лучшим после того, как «вы не можете». - person Slipp D. Thompson; 14.07.2014

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

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

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

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

person David L Morris    schedule 19.09.2008

Не совсем понимаю, о чем вы здесь спрашиваете. Вы хотите, чтобы макрос состоял из нескольких строк?

#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

Заключим x в кавычки

person PiNoYBoY82    schedule 19.09.2008

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

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

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

Пример:

#define foo(x) a+b
//should be
#define foo(x) (a+b)
person Charles Graham    schedule 19.09.2008
comment
Определение макроса не должно включать точку с запятой в конце. Благодаря этому вызов макроса выглядит и действует как вызов функции. - person Trent; 19.09.2008

Используйте \, например:

#define my_multiline_macro(a, b, c) \
if (a) { \
    b += c; \
}
person Branan    schedule 19.09.2008
comment
Это заменяется на if (a) {b + = c} без символов новой строки. Попробуйте с помощью gcc -E. - person Steve Jessop; 19.09.2008
comment
Оно делает. Но он позволяет вам редактировать новую строку в многострочном режиме, это то, что, я думаю, хотел OP. - person Branan; 19.09.2008
comment
Я думаю, что вы имели в виду ввести, позволяет вам редактировать МАКРОС в многострочном режиме - person Scott Smith; 06.03.2015