3
#define FREE1(x) do { free(x); x = NULL; } while (0);
#define FREE2(x) { free(x); x = NULL; }

What is the difference between these macros?

developer
  • 4,400
  • 5
  • 37
  • 55
  • no is not duplicated, it's a other question – developer Dec 21 '12 at 15:56
  • Did you just post two identical questions? – Carl Norum Dec 21 '12 at 15:56
  • @CarlNorum - The original question didn't include the braces around the second macro. If you look at the answers to that question, adding the braces may seem to fix the issue between the two macros. – Justin Niessner Dec 21 '12 at 15:56
  • indeed, It's not the same question. Please reopen it – developer Dec 21 '12 at 15:57
  • Voted to reopen, but didn't the answers to your other question explain this sufficiently? – Carl Norum Dec 21 '12 at 15:58
  • It's almost exactly the same. Did you even try it out? – Carl Norum Dec 21 '12 at 16:00
  • I tried and I get the same result but I'm not sure is the same code – developer Dec 21 '12 at 16:01
  • It is an exact duplicate, but not of your original question. Here is [the link](http://stackoverflow.com/q/1067226/335858). The linked question is also a duplicate, which is not surprising: this question gets asked a lot. – Sergey Kalinichenko Dec 21 '12 at 16:05
  • 1
    What kind of question is that? What is "what is the difference" supposed to mean? Is it like a game "find 10 differences"? The first macro begins with `d`, while the second one doesn't. Is this the answers you are looking for? – AnT Dec 21 '12 at 16:09

4 Answers4

12

If your question is about the do/while trick in macros, there's no difference, because you apparently made an error in the first macro definition, which completely defeated the purpose of the trick. You put the ; after the whole (0). The proper implementation should absolutely not have the ; after the while (0) in the first macro. This is the whole point of the do/while trick.

Now this code will not compile

if (condition)
  FREE2(arg);
else
  /* something else */;

This code will not compile either

do 
  FREE2(arg);
while (condition);

The point of the do/while technique is to make this code compile. But it will not compile with your FREE1 macro either because of the aforementioned error.

However, if you define the first macro correctly

#define FREE1(x) do { free(x); x = NULL; } while (0)
// No `;` at the end!!!

then the first macro will work perfectly fine in the above code samples. This is actually the reason people use the do/while technique in multi-statement macros - to make it work correctly and uniformly with ordinary functions in such contexts.

P.S. As a side note, the purpose of all such techniques is to turn a group of multiple statements into one compound statement. In your specific case the free(x); x = NULL; sequence can be re-implemented as a single expression (free(x), x = NULL), which eliminates the need for any multi-statement macro techniques, i.e. this

#define FREE3(x) (free(x), x = NULL)

will work as well. But it is a matter of personal preference.

AnT
  • 302,239
  • 39
  • 506
  • 752
5

Actually, there's no difference, C-wise.

The reason is you included a trailing semi-colon in:

#define FREE1(x) do { free(x); x = NULL; } while (0);

The reason you usually want to use do...while(0) is described here, is that you generally want to use it in if...else blocks:

if (...)
    FREE(x);
else
   ...

But with the above usage and macros this:

if (...)
   do { free(x); x = NULL; } while (0);;
else
   ...

...and...

if (...)
    { free(x); x = NULL; };
else
    ...

...are both ill-formed.

Community
  • 1
  • 1
netcoder
  • 64,266
  • 17
  • 119
  • 142
  • besides the syntactic reasons that you mentioned, the `do...while(0)` construct is usually used to allow usage of `break` from inside the block to avoid `goto` and/or code refactoring. – SomeWittyUsername Dec 21 '12 at 16:10
2

Both are half-baked attempts to fix the semicolon issue discussed in Do-While and if-else statements in C/C++ macros.

A better way to define this macro is

#define FREE3(x) do { free(x); x = NULL; } while (0)

(without the trailing semicolon.)

Community
  • 1
  • 1
NPE
  • 464,258
  • 100
  • 912
  • 987
0

This:

#define FREE1(x) do { free(x); x = NULL; } while (0);

Gets executed just once, so it's the same as:

#define FREE2(x) { free(x); x = NULL; }

But in the assembly code there is a more branch.Even if a modern compiler would probably optimize it, so with all the probabilities even the assembly code generated will be the same.

Ramy Al Zuhouri
  • 21,259
  • 23
  • 100
  • 183