Макросы многострочного препроцессора

81

Как сделать макрос многострочного препроцессора? Я умею составлять одну строчку:

#define sqr(X) (X*X)

но мне нужно что-то вроде этого:

#define someMacro(X)
    class X : public otherClass
    {
         int foo;
         void doFoo();
    };

Как я могу заставить это работать?

Это только пример, настоящий макрос может быть очень длинным.

шумный кот
источник
Вы можете легко получить ответ, выполнив поиск в SO. например, stackoverflow.com/questions/4007865/…
Forever Learner
различные методы здесь: parashift.com/c++-faq/macros-with-multi-stmts.html
Айрат
Связанный: stackoverflow.com/questions/98944/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Ответы:

123

Вы используете \как escape-символ продолжения строки.

#define swap(a, b) {               \
                       (a) ^= (b); \
                       (b) ^= (a); \
                       (a) ^= (b); \
                   }

РЕДАКТИРОВАТЬ: как @abelenky указал в комментариях, \символ должен быть последним символом в строке . Если это не так (даже если это будет просто пробел), вы получите запутанные сообщения об ошибках в каждой строке после него.

Эд С.
источник
44
Предупреждение: убедитесь, что \ - последний символ в строке. В C пробелы обычно не имеют значения, но в этом случае невидимые пробелы в конце строки могут вас убить.
abelenky 02
2
Однако следует добавить, что получившийся текст находится в одной строке. Поскольку C обрабатывает все пробелы между токенами одинаково, это обычно не имеет большого значения, но все же.
Питер - Восстановите Монику
Еще я бы посоветовал разместить ` after all useful lines of the macro, and add a comment afterward saying something like // пустую строку после макроса . It's sometimes easier to ensure that all lines of a macro end with `, чтобы это было сделано во всех строках, кроме последней.
supercat
Я не знал, что вы можете использовать такой побитовый xor для обмена переменными, но мне жаль, что у меня не было этого !!!
cmarangu
18

Вы можете сделать макрос охватывающим несколько строк, поместив обратную косую черту ( \) в конце каждой строки:

#define F(x) (x)   \
              *    \
             (x)
Керрек С.Б.
источник
18

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ, как указали Керрек С.Б. и coaddict, что должно было быть указано в принятом ответе, ВСЕГДА помещайте фигурные скобки вокруг своих аргументов. Пример sqr - это простой пример, изучаемый на курсах CompSci.

Вот в чем проблема: если вы определите это так, как вы это сделали, что произойдет, когда вы скажете «sqr (1 + 5)»? Вы получите «1 + 5 * 1 + 5» или 11
Если вы правильно разместите вокруг него фигурные скобки, #define sqr(x) ((x)*(x))
вы получите ((1 + 5) * (1 + 5)) или то, что мы хотели 36 ... красиво.

Эд С. будет иметь ту же проблему с "свопом"

дживетурция
источник
как насчет sqr(++i)? (предположим, что у нас есть int i) :)
Géza Török
Я сделал это как упражнение и, по-видимому i, увеличивается по мере того, как он подставляется в макрос (в этом случае он заменяется дважды), а затем он умножается. Итакsqr(++5) == ((7) * (7))
jiveturkey
2
@ GézaTörök Расширение sqr(++i)to ((++i)*(++i))вызовет неопределенное поведение, потому что значение iмодифицируется более одного раза в этом операторе (нет точки последовательности между операциями).
moooeeeep
5

Вам нужно экранировать новую строку в конце строки, экранировав ее с помощью \:

#define sqr(X) \
        ((X)*(X))
codaddict
источник