2

What is the difference (if any) between:

#define BUF (8)

and

#define BUF 8

I am not very experienced in c programming and have never saw the #define with only 1 number and than putting it in brackets.

PS: Code is compiled on 64-bit linux system using gcc with -m32 flag. So the final binary is 32-bit ELF executable.

  • 1
    No there is none. You use `()` when you want to specify order of operations or to make your code clearer. – Xantium Apr 16 '19 at 18:55
  • 4
    @Simon There is a slight difference. E.g. `float x = sin BUF;` will compile in one case but not the other. – HolyBlackCat Apr 16 '19 at 18:56
  • 1
    Possible duplicate of [Is there a good reason for always enclosing a define in parentheses in C?](https://stackoverflow.com/questions/9081479/is-there-a-good-reason-for-always-enclosing-a-define-in-parentheses-in-c) – Evil Apr 16 '19 at 18:57
  • 1
    Yes..I believe the answers there are very informative. Shame on me for not finding this myself. – NonStandardModel Apr 16 '19 at 19:01
  • 3
    @Simon: Yes, there is a difference. If some other macro uses `##` with `BUF`, the `8` may produce a valid token where the `(8)` would not. – Eric Postpischil Apr 16 '19 at 19:08
  • 1
    Anyhow guys .. you have some incredible community here. In few minutes after asking the question I have gotten 3 answers. Top response ! – NonStandardModel Apr 16 '19 at 19:16
  • the main reason to enclose the value `8` in parens is because often the process of 'direct text replacement' (which the compiler does) can result in a unexpected code string. what the parens do is group the parameter value together. That does not make any difference in the posted example, but makes a drastic difference in more complex macros – user3629249 Apr 18 '19 at 17:33

3 Answers3

7

Appearances of an in-scope macro identifier are simply replaced by the replacement text. Thus, this code ...

#define BUF 8
#define BUF2 (8)

x =  BUF * BUF2;

... expands to

x = 8 * (8);

In particular, the parentheses are part of the replacement text, not part of the macro definition. (But do not confuse this with function-like macro definitions, where there is no space between the identifier and the opening parenthesis.)

In that case, the two macro definitions can be used almost, but not completely, interchangeably. The parentheses make a bigger difference in other contexts however. Consider this:

#define MY_SIZE 16 + 7
#define MY_SIZE2 (16 + 7)

void *x = malloc(8 * MYSIZE);
void *y = malloc(8 * MYSIZE2);

It expands to

void *x = malloc(8 * 16 + 7);
void *y = malloc(8 * (16 + 7));

, which reserves different amounts of memory for x and y.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
6

I cannot imagine it making any difference when used sensibly in this particular case, but consider this:

#define add(x,y) x+y

int i=add(3,5)*2

Now you would expect i to have the value 16, right?, but it would expand to i=3+5*2, giving i the value 13.

HolyBlackCat wrote in a comment that float x = sin BUF; would not compile in the latter case, and this is completely true. However, using macros like that is a VERY bad idea.

Putting parenthesis around never hurts and often helps. Macros are basically just an advanced copy paste. So if you can imagine a piece of code where the character sequence (8) would yield another result than 8, then those two macros will differ in the same way.

For similar reasons, if a macro contains several statements, it is a good idea to enclose them in a do-while loop. Consider this:

#define callMy2Funcs(x,y) \
    myFunc1(x); \
    myFunc2(y);

Now this:

if(x>5) 
    callMy2Funcs(x,x);

will expand to

if(x<5)
    myFunc1(x);
myFunc2(x);

instead of

if(x<5) {
    myFunc1(x);
    myFunc2(x);
}

The solution is this:

#define callMy2Funcs(x,y) \
    do {\
        myFunc1(x); \
        myFunc2(y); \
    } while(0)
klutt
  • 30,332
  • 17
  • 55
  • 95
  • As I understand it `#define` should be a constant – Xantium Apr 16 '19 at 18:58
  • 2
    @Simon #define defines a MACRO. Some people say macros should only be used for defining constants. (IMHO those people are wrong!) – phonetagger Apr 16 '19 at 18:58
  • 2
    @ikegami Please don't make edits when a post is fresh. It makes it annoying when I'm in the process of improving my post. – klutt Apr 16 '19 at 19:12
  • @SergeyA True. Fixed. – klutt Apr 16 '19 at 19:13
  • 1
    @ikegami Sorry, did not mean to be ungrateful. But is better to point it out in a comment instead. On an old post you can edit it without commenting. And thank you for fixing it. – klutt Apr 16 '19 at 19:32
  • Leaving a comment, leaving myself a note to follow up on the comment, and following up on that comment would be far more annoying. Just because it might save you from pressing Ok if you happen to be editing? And all this while, a pretty crucial (even if minor) typo remains. The edit was important *because* the post was (relatively) fresh. – ikegami Apr 16 '19 at 19:35
  • @ikegami Correct me if I'm wrong, but I cannot post the new edit before I have reloaded your new version, right? – klutt Apr 16 '19 at 19:51
  • Unless it's changed, a dialog pops up asking if you want to proceed despite the edit or not. – ikegami Apr 16 '19 at 19:53
  • @ikegami And if I proceed (which I think 99% will do without reading) I will just overwrite your edit? – klutt Apr 16 '19 at 19:54
  • Yup. It's still there in the history to be viewed – ikegami Apr 16 '19 at 19:55
  • @ikegami Well, then that's an argument against your method. In order to make sure that your edit stays, you still have to return to the post to check if your edit got overwritten. – klutt Apr 16 '19 at 19:57
  • @ikegami You have a point that it was an important fix, but I still think it is better to just put it in a comment. The annoying part for me to click ok was a minor thing that's far less important than the need to fix it. But as I said, most people would just replace your edit without even reading it. – klutt Apr 16 '19 at 20:01
2

In case of such simple macro definition - just a constant - there's no real need to enclose that 8 into (). This pair of () might prevent some abuse, but the examples would be contrived and unrealistic.

But once operators get involved, i.e. the substituted text is intended to be an expression, adding those () becomes significantly more important. For example, if you have a sequence of related manifest constant definitions that involve negative values as well, adding those () to substitutions that use unary - is a very good idea

#define CONSTANT_A 2
#define CONSTANT_B 1
#define CONSTANT_C 0
#define CONSTANT_D (-1)

In this case, just for the sake of consistency it might make sense to enclose all of them into (). It is a matter of personal taste.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765