Багаторядкові макроси препроцесора


81

Як створити багаторядковий макрос попереднього процесора? Я знаю, як зробити один рядок:

#define sqr(X) (X*X)

але мені потрібно щось подібне:

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

Як я можу змусити це працювати?

Це лише приклад, справжній макрос може бути дуже довгим.


Ви можете легко отримати відповідь, шукаючи SO. наприклад, stackoverflow.com/questions/4007865/…
назавжди учень


Відповіді:


123

Ви використовуєте \в якості символу продовження рядка втечу.

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

EDIT: Як зазначив @abelenky у коментарях, \персонаж повинен бути останнім символом у рядку . Якщо це не так (навіть якщо після цього буде лише пробіл), ви отримаєте заплутані повідомлення про помилки в кожному рядку після нього.


44
Слово обережності: переконайтесь, що \ - останній символ у рядку. У C пробіли зазвичай не мають значення, але в цьому випадку невидимі пробіли в кінці рядка можуть вбити вас.
abelenky

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

ЗВЕРНІТЬ ЗАУВАЖЕННЯ, як вказували Керрек С.Б. та спільний вирок, на який слід було б вказати у прийнятій відповіді, ЗАВЖДИ розміщуйте дужки навколо ваших аргументів. Приклад 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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.