61

Clearly, there are times where #define statements must have parentheses, like so:

#define WIDTH 80+20

int a = WIDTH * 2; // expect a==200 but a==120

So I always parenthesize, even when it's just a single number:

#define WIDTH (100)

Someone new to C asked me why I do this, so I tried to find an edge case where the absence of parentheses on a single number #define causes issues, but I can't think of one.

Does such a case exist?

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
weston
  • 54,145
  • 21
  • 145
  • 203
  • I'll just leave this here: http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5 (Look for the links on why `#define` macros are evil). – Tim Reddy Jan 31 '12 at 18:29
  • @TReddy Thanks, but you wouldn't replace a `#define WIDTH (100)` with `inline int width() { return 100; }` would you?! – weston Feb 01 '12 at 09:33
  • No, I wanted to share links on why macros are evil and those links happened to be collected under that section about inline functions (which is orthogonal to your question). In your situation, does a macro give you better results than a `static int width = 80+20`? – Tim Reddy Feb 01 '12 at 14:33
  • 1
    @TReddy That is a good point, a quick test shows the only real downside is that I get a bunch of warnings where it's defined in an .h file, but not used in every .c file that includes it. Maybe that warning can be turned off, and then it would be a viable alternative. – weston Feb 01 '12 at 15:22
  • `#define 100 50+50` (no, this doesn't actually work) – Philip Feb 02 '12 at 09:09
  • 1
    @Philip Thankfully! What hell would a typo there cause! `#define 100 50-50` – weston Feb 02 '12 at 12:41
  • For anyone interested, the link posted by @TimReddy went offline sometime in 2015. It's now available here: https://isocpp.org/wiki/faq/inline-functions#inline-vs-macros. But to summarize, it outlines 4 different downfalls of `#define` macros: multiple invocations of the arguments, nested if statements being compiled incorrectly, multiple statements in a macro causing syntax errors, and concatenated token trickery. – Derek Redfern Jul 22 '16 at 17:35

9 Answers9

51

Yes. The preprocessor concatenation operator (##) will cause issues, for example:

#define _add_penguin(a) penguin ## a
#define add_penguin(a) _add_penguin(a)

#define WIDTH (100)
#define HEIGHT 200    

add_penguin(HEIGHT) // expands to penguin200
add_penguin(WIDTH)  // error, cannot concatenate penguin and (100) 

Same for stringization (#). Clearly this is a corner case and probably doesn't matter considering how WIDTH will presumably be used. Still, it is something to keep in mind about the preprocessor.

(The reason why adding the second penguin fails is a subtle detail of the preprocessing rules in C99 - iirc it fails because concatenating to two non-placeholder preprocessing tokens must always result in a single preprocessing token - but this is irrelevant, even if the concatenation was allowed it would still give a different result than the unbracketed #define!).

All other responses are correct only insofar that it doesn't matter from the point of view of the C++ scanner because, indeed, a number is atomic. However, to my reading of the question there is no sign that only cases with no further preprocessor expansion should be considered, so the other responses are, even though I totally agree with the advice contained therein, wrong.

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • Actually, for me this compiles fine as long as I define a `penguin200` and a `penguin(int a)` function. It seems to have no trouble concattinating penguin and (100) to form `penguin(100)` which is calls successfully. I might be using C89 however. – weston Jan 31 '12 at 15:18
  • 1
    Yes, this may be due to different preprocessor specifications (`gnu cpp` fails it on my machine). But I think we agree that this is not relevant to the question ... – Alexander Gessler Jan 31 '12 at 15:20
  • 4
    Well technically I asked for cases where the absence of brackets created issues. This is an issue caused by the presence of brackets. It's a better answer than "there is no difference" however. – weston Jan 31 '12 at 15:24
  • 4
    @Lundin Good for you. But plenty of people use it and *need* it. Boost for instances makes some great use of token pasting that cannot be replaced. I have also already needed it in a library and I know of no workaround for my case. – Konrad Rudolph Jan 31 '12 at 19:30
  • 1
    I wouldn't ban `##` as @Lundin suggests, but if you use it, you should know what you're doing. So requiring parentheses around macros because of this seems wrong. It's an interesting preprocessor corner, but isn't relevant for "normal" preprocessor usage. – ugoren Jan 31 '12 at 22:12
  • @AlexanderGessler your answer really helps me. Because i am searching for this answer many days. Thanks much. – RaHuL May 27 '21 at 13:46
32

Sometimes you have to write code not with the current caveats in mind, but with the ones of next time it is going to be edited.

Right now your macro is a single integer. Imagine someone editing it in the future. Let's say they are not you, but someone who is less careful or in more in a hurry. The parentheses are there to remind people to put any modifications within them.

This kind of thinking is a good habit in C. I personally write code in a style which some people might find "redundant", with things like this but especially with regards to error handling. Redundancy is for maintainability and composability of future editings.

Davide Cannizzo
  • 2,826
  • 1
  • 29
  • 31
asveikau
  • 39,039
  • 2
  • 53
  • 68
  • 4
    If that someone knows that non-trivial macros need parenthesis, he'll add them when changing. If not, he'll create a mess, no matter what you do. So I'm against adding parenthesis which are clearly not needed. But it's a matter of opinion. – ugoren Jan 31 '12 at 15:06
  • 4
    I don't agree - you shouldn't need to concern yourself with the possibility of non-programmers maintaining your code in the future. Parenthesis around macro expressions is such a basic thing, you should be able to assume that every C programmer knows about it. Otherwise by using the same argument, you should put parenthesis around _everything_: `int x = y + z;` (not a macro) should then with the same flawed logic always be written as `int x = (y + z);`, in case a stressed non-programmer will maintain the code in the future, to remind them of the dangers of operator precedence. – Lundin Jan 31 '12 at 15:14
  • 3
    OK guys, then I disagree with your disagreement. :-) As for @Lundin's comments in particular, I'm not talking about non-programmers so much as bad or uncareful programmers - which seem to exist in droves and in some work environments you can't control who will maintain your code down the line. But even if you have a pool of decent programmers, maybe the parenthesis isn't the best example but I strongly believe adding more lines and characters can often make edits more "composable" - we shouldn't always strive to write the shortest code possible simply because we can. – asveikau Jan 31 '12 at 15:28
  • It's the same argument as having braces around `if(foo) { bar() }`. Sure, you could leave the braces out. It's obvious you'll need them when you add `baz()`. Perfectly obvious until you get to 3 in the morning... – Chris Burt-Brown Jan 31 '12 at 16:24
  • I agree with @ChrisBurt that it’s the same as having braces around all blocks but I disagree with his conclusion: I’ve never bought this “oh you could forget it” argument. In my experience this is simply never an issue, making the potential problem entirely theoretical. – Konrad Rudolph Jan 31 '12 at 19:40
  • asveikau's idea of thinking about future programmers is valid, though I think `#define A (0)` isn't the place for it. With @ChrisBD's `if(foo){bar();}`, I'd wouldn't use braces, but I would if `bar()` is in a separate line. But it isn't always clear where the balance is. – ugoren Jan 31 '12 at 19:47
  • @asveikau If they are bad programmers, the best favour you can do them is to write as normal code as possible. Let them learn by their mistakes, rather than teaching them to be afraid of C. For example there are countless of programmers who put parenthesis around a `return` expression without knowing why, they picked it up from someone else who taught them to fear the C language. Similarly there are countless of programmers who typecast the result of malloc() (which is just wrong and dangerous practice) without knowing why they do it. – Lundin Feb 01 '12 at 07:33
  • @ChrisBurt-Brown No it isn't the same argument, because a normal if statement takes up several lines and you can get tricked by the indention if you aren't using {}. For reference, MISRA-C:2004 bans `if` without {} but it allows #define constants without (). They do that for a reason. – Lundin Feb 01 '12 at 07:36
  • @Lundin: Perhaps I should say *analogous to* rather than *the same argument*. I do agree that () around a define is pretty pessimistic outlook. And I'm C++ anyway; I just use `const int` :P – Chris Burt-Brown Feb 01 '12 at 09:31
  • Adding extraneous brackets "in case a beginner changes a single number to something" else is pretty silly IMO. You may as well bin all your code. Write as normal code as you can and let the "beginner" figure it out. We dont write code for the lowest common denominator. – RichieHH Oct 05 '21 at 04:51
10

As Blagovest Buyukliev said:

The define consists of a single token (one operand only, no operators), the parentheses are not needed because a single token (such as 100) is an indivisible atom when lexing and parsing.

But I would recommend the following rules when it comes to macros:

  1. Avoid function like macros @see Lundin's comment.

If you want to use function like macros badly consider the following 2 rules:

  1. Always use brackets for arguments in macros
  2. Only use an macro argument once

Why rule 1.? (To keep the order of the operations correct)

#define quad(x) (x*x)
int a = quad(2+3);

will expand to:

int a = (2+3*2+3);

Why rule 2.? (To ensure a side effect is only applied once)

#define quad(x) (x*x)
int i = 1;
int a = quad(i++);

will expand to:

int a = i++ * i++;
Community
  • 1
  • 1
Nicola Coretti
  • 2,655
  • 2
  • 20
  • 22
  • 1
    Thinking about this for a bit, a function-like macro could make reference to a non-argument in-context variable, whereas an inline can't. But like you said, there's no real good reason to use such a thing. I was a part of a very large code review at a former employer where we ended up writing a lot of inlines, against company coding policy, to replace tons of replicated code scattered throughout our part of the OS that otherwise would have been written as function-like macros. We ended up going from the #1 source of bugs to being a model of how to do it right. – Andrew Beals Jan 31 '12 at 15:53
  • 1
    @Lundin one single case is generic "functions" like `max`. In C++ you could implement them as multi-parameter templates. The only really flexible option in C for this is a function-like macro. – Ruslan Feb 22 '18 at 07:19
9

When code defines only a number, @Alexander Gessler well answers the question.

Yet many coders do not notice the unary operators in the following:

#define TEMPERATURE1M (-1)
#define TEMPERATURE1P (+1)

When code uses a #define that employs an operator, enclosing () insures expected numeric results and precedence.

#define TEMPERATURE_WITH  (-1)
#define TEMPERATURE_WITHOUT -1

// Consider how these will compile
int w  = 10-TEMPERATURE_WITH;
int wo = 10-TEMPERATURE_WITHOUT;  // May not compile

The last line of code may compile given C99 semantic changes @Olaf

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
8

Whenever the define consists of a single token (one operand only, no operators), the parentheses are not needed because a single token (such as 100) is an indivisible atom when lexing and parsing.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
7

Since 100 is a single token, I doubt you'll find a corner case where the parentheses matter (for a single token!)

It's still a good habit IMO, since they can matter when there are multiple tokens involved.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
6

No. There is no case where #define WIDTH 100 can yield an unambiguous or "surprising" expansion. That's because it can only result in a single token being replaced by a single token.

As you know, macro confusion ensues when a single token (e.g. WIDTH) results in multiple tokens (e.g. 80 + 20). As far as I can surmise, that's the only cause for the use of parentheses in substitutions and, as explored in my first paragraph, it doesn't apply here.

However, this technical fact aside, it may still be a good practice. It promotes habit, and it also serves as a reminder if that macro ever gets modified to something more complex.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

There's a good reason, sometimes.

For a single number, there's no good reason.

For other cases, as you have shown yourself, there is a good reason.

Some people prefer to be extra careful, and always use the parentheses (@aix recommends it. I don't, but there's no hard answer).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
ugoren
  • 16,023
  • 3
  • 35
  • 65
2

It certainly won't hurt and it is a good habit. But there is no difference between (100) and 100 for numerical calculations.

Jack Edmonds
  • 31,931
  • 18
  • 65
  • 77