Multi Line Preprocessor Macros

Multi line preprocessor macros

You use \ as a line continuation escape character.

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

EDIT: As @abelenky pointed out in the comments, the \ character must be the last character on the line. If it is not (even if it is just white space afterward) you will get confusing error messages on each line after it.

Multiline preprocessor macro with trailing comments

The problem is that the c-preprocessor just adds another line ending character when the \ is hit and continuated.

Within // comments you can't do that. The \ character isn't accepted to continuate the comment (it's supposed to appear as a single line anyway).


The solution is,- as you found out yourself -, to use the /**/ comment style.

Can we write a macro in many lines without the backslash at the end?

Multi-line macro definitions without backslash-newline

Since comments are replaced by spaces in translation phase 3:


  1. The source file is decomposed into preprocessing tokens7) and sequences of
    white-space characters (including comments). A source file shall not end in a
    partial preprocessing token or in a partial comment. Each comment is replaced by
    one space character. New-line characters are retained. Whether each nonempty
    sequence of white-space characters other than new-line is retained or replaced by
    one space character is implementation-defined.

and the preprocessor runs as phase 4:


  1. Preprocessing directives are executed, macro invocations are expanded, and
    _Pragma unary operator expressions are executed. If a character sequence that
    matches the syntax of a universal character name is produced by token
    concatenation (6.10.3.3), the behavior is undefined. A #include preprocessing
    directive causes the named header or source file to be processed from phase 1.
    through phase 4, recursively. All preprocessing directives are then deleted.

it is possible, but absurd, to write a multi-line macro like this:

#include <stdio.h>

#define possible_but_absurd(a, b) /* comments
*/ printf("are translated"); /* in phase 3
*/ printf(" before phase %d", a); /* (the preprocessor)
*/ printf(" is run (%s)\n", b); /* but why abuse the system? */

int main(void)
{
printf("%s %s", "Macros can be continued without backslashes",
"because comments\n");
possible_but_absurd(4, "ISO/IEC 9899:2011,\nSection 5.1.1.2"
" Translation phases");
return 0;
}

which, when run, states:

Macros can be continued without backslashes because comments
are translated before phase 4 is run (ISO/IEC 9899:2011,
Section 5.1.1.2 Translation phases)

Backslash-newline in macro definitions

Translation phases 1 and 2 are also somewhat relevant:

  1. Physical source file multibyte characters are mapped, in an implementation-defined
    manner, to the source character set (introducing new-line characters for
    end-of-line indicators) if necessary. Trigraph sequences are replaced by
    corresponding single-character internal representations.

The trigraph replacement is nominally relevant because ??/ is the trigraph for a backslash.


  1. Each instance of a backslash character (\) immediately followed by a new-line
    character is deleted, splicing physical source lines to form logical source lines.
    Only the last backslash on any physical source line shall be eligible for being part
    of such a splice. A source file that is not empty shall end in a new-line character,
    which shall not be immediately preceded by a backslash character before any such
    splicing takes place.

This tells you that by the time phase 4 (the preprocessor) is run, macro definitions are on a single (logical) line — the trailing backslash-newline combinations have been deleted.

The standard notes that the phases are 'as if' — the behaviour of the compiler must be as if it went through the separate phases, but many implementations do not formally separate them out fully.


Avoid the GCC extension

The expanded example (quote from the GCC manual) has the invocation spread over many lines, but the definition is strictly on one line. (This much is not a GCC extension but completely standard behaviour.)

Note that if you're remotely sane, you'll ignore the possibility of putting preprocessing directives within the invocation of a macro (the #undef and #define in the example). It is a GCC extension and totally unportable. The standard says that the behaviour is undefined.

Annex J.2 Undefined behavior


  • There are sequences of preprocessing tokens within the list of macro arguments that would otherwise act as preprocessing directives (6.10.3).

how to combine multiline macros in C with comments at the end of a line

According to a comment, It seems to be an XY-problem. A macro might not be the best approach.

If you are up to a table of constants, the normal way would be just to generate an array once and use that throughout your code:

static const float cal_table [5] = {
0.001, // 5 mV
0.002, // 10 mV
0.004, // 20 mV
0.007, // 35 mV
0.013 // 65 mV
};

If that is only used in a single file, make it static as shown, else remove the static and add

extern const float cal_table[5];

to the header file of the module.

Note that, if this is for a small MCU (AVR/PIC) without floating point unit, you might be better off with not using float, but fixed-point simulated by integers (e.g. scaled to 1mV).

You can also use this as an initializer for an auto array variable. Make that array a typedef, generate the const as described and memcpy the array to the local variable as required. This is as fast as an initializer, because the compiler also has to copy that to the local array. So you use the const array as a template (still having a single location to change, if required) .

python regex to match multi-line preprocessor macro

This is a simple test program I knocked up:

#!/usr/bin/env python

TEST1="""
#include "Foo.h"
#define bar foo\\
x
#include "Bar.h"
"""

TEST2="""
#define bar foo
#define x 1 \\
12 \\
2 \\\\ 3
Foobar
"""

TEST3="""
#define foo(x) if(x) \\
doSomething(x)
"""

TEST4="""
#define foo(x) if(x) \\
doSomething(x)
normalCode();
"""

import re
matcher = re.compile(r"^[ \t]*#define(.*\\\n)+.*$",re.MULTILINE)

def extractDefines(s):
mo = matcher.search(s)
if not mo:
print mo
return
print mo.group(0)

extractDefines(TEST1)
extractDefines(TEST2)
extractDefines(TEST3)
extractDefines(TEST4)

The re I used:

r"^[ \t]*#define(.*\\\n)+.*$"

Is very similar to the one use used, the changes:

  1. [ \t] To avoid newlines at the start
    of the define.
  2. I rely on + being
    greedy, so I can use a simple .*$ at
    the end to get the first line of the
    define that doesn't end with \


Related Topics



Leave a reply



Submit