64

I am not an expert, so go easy on me. Are there any differences between these two code segments?

#define BIT3 (0x1
<
<
3)
static int a;

and

#define BIT3 (0x1 << 3) static int a;

Also, is there a way to write the first in one line? What is the point of this multi-line style? Is the following code good?

#define BIT3 (0x1 << 3)
static int a;
Adam S
  • 8,945
  • 17
  • 67
  • 103
  • The first fragment has two consecutive `<` (less than) operators and no `<<` (shift) operator. It also has an object-like macro with the value `(0x1`, followed by 3 lines that are meaningless (they're not part of the macro definition; there'd have to be trailing backslashes on the lines for that), and the declaration. The second fragment is quite different, but even more unusable. The `(0x1 << 3)` expression of itself is fine, but followed by the `static` definition is just a syntax error; you need a semicolon after the close parentheses to be in with a fighting chance. So they're different!! – Jonathan Leffler Apr 15 '20 at 17:04

3 Answers3

109

A multi-line macro is useful if you have a very complex macro which would be difficult to read if it were all on one line (although it's inadvisable to have very complex macros).

In general, you can write a multi-line define using the line-continuation character, \. So e.g.

#define MY_MACRO    printf( \
    "I like %d types of cheese\n", \
    5 \
    )

But you cannot do that with your first example. You cannot split tokens like that; the << left-shift operator must always be written without any separating whitespace, otherwise it would be interpreted as two less-than operators. So maybe:

#define BIT3 (0x1 \
    << \
    3) \
    static int a;

which is now equivalent to your second example.

[Although I'm not sure how that macro would ever be useful!]

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • Actually, it's from a guide on writing cross-platform code for different embedded devices. It's the safe way of "defining" a third bit, because different systems may use a different number of bytes for a given variable type. – Adam S Jun 09 '11 at 00:44
  • 6
    @Adam: Hmm, I don't follow! When would `(0x1 << 3) static int a` ever be valid syntax? – Oliver Charlesworth Jun 09 '11 at 07:24
  • Sorry, I thought I followed your answer until: `[Although I'm not sure how that macro would ever be useful!]` I must confess I've no idea what **that** refers to in this context. If `#define BIT3 (0x1 << 3) static int a;` is not valid syntax then it is not a macro (I shudder to think that might compile somewhere). In that case **that macro** cannot be referring to it despite your pithy comment. – ebyrob Jan 05 '18 at 14:36
  • @ebyrob - This answer is 6 years old, so I'm not too sure either :) I think I was saying that whilst `#define BIT3 (0x1 << 3) static int a;` **is** a valid macro, the code it generates is not valid (and thus the macro serves no useful purpose). – Oliver Charlesworth Jan 05 '18 at 15:53
  • @OliverCharlesworth Well, you showed me that `\\` is indeed the correct line terminator for multi-line macros, but I can certainly see how the questioner may have been a bit confused by advanced topics. I'm not sure I'd consider a "macro" that can't exist anywhere other than definition without compile error "a valid macro" (except when generating such an error is its obvious purpose) but I digress. – ebyrob Jan 05 '18 at 17:46
  • What if I want it to include few lines? Namely I want its expansion to spread over few lines? – Royi Sep 24 '18 at 17:01
21

For example:

#define fact(f,n)   for (f=1; (n); (n)--) \
                      f*=n;

You can separate the lines with the \ character. Note that it is not macro specific. You can add the \ character in your code whenever you would like to break a long line.

phoxis
  • 60,131
  • 14
  • 81
  • 117
  • Interesting. Does it serve any useful purpose outside of a macro? – Oliver Charlesworth Jun 08 '11 at 16:21
  • Definitely it does. Like you have a long long `printf` or some statement, but you want to manually wrap it, then it comes in handy. – phoxis Jun 08 '11 at 16:22
  • 2
    Yes, and back when it was not allowed to concatenate string constants, it was quite handy. This was not allowed: "a string" " continued". – Prof. Falken Jun 08 '11 at 16:24
  • @Oli Charlesworth, now that I (maybe) have your attention, have you seen this: http://stackoverflow.com/questions/3152497/vhdl-verilog-related-programming-forums/5564577#5564577 – Prof. Falken Jun 08 '11 at 16:26
  • What if I want it to include few lines? Namely I want its expansion to spread over few lines? – Royi Sep 24 '18 at 17:01
8

The first one should not work. Lines should be separated with backslash THEN newline. Like so:

#define SOME_MACRO "whatever" \
"more" \
"yet more"
Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • 6
    More to the point the line terminator should be escaped with a backslash. If you put a space after the backslash you'll get some extreme hissy fits from the preprocessor. – JUST MY correct OPINION Jun 08 '11 at 15:36
  • What if I want it to include few lines? Namely I want its expansion to spread over few lines? – Royi Sep 24 '18 at 17:01
  • @Royi if what you want is multi-line string literals, it can be done in C++ (But not in C.) https://stackoverflow.com/a/5460235/193892 – Prof. Falken Sep 25 '18 at 09:27
  • But I need the string for the Pre Process phase, not in the program. Think of defining few `#pragma` (Each in its own line) in one `#define ALL_PRAGMAS`. – Royi Sep 25 '18 at 09:31
  • @Royi, I am not sure then what you mean. Would it help to just put `\` at the end of each line? Maybe you should open a question. – Prof. Falken Sep 25 '18 at 10:56
  • Assume you have `#pagma somePragmaA` then new line `#pagma somePragmaB` then new line `#pagma somePragmaC`. Those are pragmas hence must be in new line each. Say you use them a lot in the code hence you want to create a single macro which will expand to them with by the Pre Processor. Can it be done? – Royi Sep 25 '18 at 11:03
  • @Royi - now I understand what you want! I think so, yes: https://stackoverflow.com/a/3030312 – Prof. Falken Sep 25 '18 at 11:29