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. – Simon Apr 16 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 at 18:56
  • 1
  • 1
    Yes..I believe the answers there are very informative. Shame on me for not finding this myself. – NonStandardModel Apr 16 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 at 19:08
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)
  • As I understand it #define should be a constant – Simon Apr 16 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 at 18:58
  • 1
    Why would you expect 30??? (3 + 5) * 2 = 16! – SergeyA Apr 16 at 19:09
  • 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 at 19:12
  • 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 at 19:32
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.

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.