1
#define swap(t, x, y) \
  do { \
   t safe ## x ## y; \
   safe ## x ## y = x; \
   x = y; \
   y = safe ## x ## y; \
  } while (0)

The code swaps arguments x and y of type t.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
AcidBurn
  • 199
  • 1
  • 11

3 Answers3

3

The ## (double number sign) operator concatenates two tokens in a macro invocation (text and/or arguments) given in a macro definition. Read More

Sourav Kanta
  • 2,727
  • 1
  • 18
  • 29
2

The double pound sign ## is used for token concatenation.

This is how your code would look without pound key for simplicity.

#define swap(t, x, y) \
  do { \
   t safexy; \
   safexy = x; \
   x = y; \
   y = safexy; \
  } while (0)

You need to abide by the following rules when using ##

  • The ## operator cannot be the very first or very last item in the replacement list of a macro definition.
  • The last token of the item in front of the ## operator is concatenated with first token of the item following the ## operator.
  • Concatenation takes place before any macros in arguments are expanded. If the result of a concatenation is a valid macro name, it is available for further replacement even if it appears in a context in which it would not normally be available.

  • If more than one ## operator and/or # operator appears in the replacement list of a macro definition, the order of evaluation of the operators is not defined.

For more understanding read here.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Vinay Shukla
  • 1,818
  • 13
  • 41
2

When you invoke this macro, for example like this:

swap(double, a, b);

it gets replaced by inline code to swap the two values, namely:

do {
   double safeab;
   safeab = a;
   a = b;
   b = safeab;
} while (0);

Things to note:

  • The swap requires a temporary variable. In order to create this variable, the type must be known. (Some compilers allow you to use typeof(a), but that's not standard and thus not portable.)
  • The name of the temporary variable is made up of the names of the variables to be swapped by means of the preprocessor's concatenation operator ##. This operator is available only in macro bodies and creates a new token by pasting the adjacent tokens together. Note that the name creation fails if one of the swapping operands are compound, e.g. a[i] or p->x. The name creation by concatenation is a bit overcareful. Because the swapping takes place in its own scope, it is safe to shadow variables, except those being swapped of course. Just pick a name outside your regular naming conventions and cross your fingers.
  • The do { ... } while (0) wrapper is a common method to make the macro behave like a function, which is important if they are used as the only expression of an if or while body.
  • The backslashes at the end allow you to spread a macro over various lines. It is customary to line them up nicely at the end, so that they don't clutter the code.

Given that the macro doesn't work for compound expressions, you don't buy much with it. It also isn't type generic, because when you invoke the macro, the type must be known. Write a small static function for swapping; that's clearer in my opinion.

The C FAQ has a question and strong opinions about type-generic swap macros, too.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • Since you can't swap compound expressions anyway, I'm not sure that the 'Given' clause is really applicable. You can only swap … hmm, l-values, I suppose. – Jonathan Leffler Jun 21 '15 at 06:39
  • @JonathanLeffler: Well, you can swap, say, `a[i]` and `a[j]` or `p->x`and `p->y`, can't you? That won't concatenate to a valid variable name and isn't a "simple" one-token expression. Maybe "compound expression" isn't a good word; I've used "compound" here as it is used in "compound literal", namely to refer to compound data types. – M Oehm Jun 21 '15 at 08:06
  • By the way, I'm also not sure that the question is exclusively about the `##` operator, as everyone here seems to assume. The original, admittedly rather vague question title was "How does this code work?". – M Oehm Jun 21 '15 at 08:10
  • Fair point on expressions such as subscripted array elements; the elaborate temporary variable name gets wrecked. I don't really see there was anything else (out her than the `##`) to confuse the OP. – Jonathan Leffler Jun 21 '15 at 08:15
  • @M Oehm The do { ... } while (0) wrapper is a common method to make the macro behave like a function, which is important if they are used as the only expression of an if or while body. - I couldn’t understand this point. Can you please explain why it is important to use the wrapper if used as the only expression? – Shyam Oct 31 '15 at 14:37
  • 1
    @Shyam: The macro looks like a function, so it will be used like a function in code. But it expands to more than one statement. if you have `if (x) MACRO(a);` and it expand to `if (x) first(a); second(a);` you get a surprise: `second(a)` will be called unconditionally. The wrapper prevents this. – M Oehm Oct 31 '15 at 15:29
  • Got it! Thanks much @M Oehm – Shyam Oct 31 '15 at 16:48