Solving the temporary storage problem of C macros, to implement an inverse comma operator

NOTE: I was mistaken when I said that the initializer order is guaranteed, see here. Bear that in mind.

Motivation

We often want to write macros that store some temporary data. Take the standard way of implementing swap:

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

This is icky because any variable name we choose could clash with one already in the caller namespace. What's more, we have to stick it in this do while thing which (1) prevents the macro being used as an expression, and (2) stops the value itself escaping out (i.e. returning a value).

(We use a do while so that the macro behaves more like a regular statement, see here.)

Overview

We can implement swap much better using an inline struct declaration along with a compound initializer.

I start by implementing an operator of my own invention, fst, the comma operator's complement1. fst evaluates its first operand, evaluates its second, then returns the value of the first.

#define fst(x, y)              \
    ((struct {                 \
        __typeof__(x) first;   \
        __typeof__(y) second;  \
    }) {                       \
        .first = (x),          \
        .second = (y)          \
    }.first)

An explanation of fst

The first three lines of the macro define an unnamed struct with fields for the operands. We then use compound literal syntax to declare an unnamed stack variable of this struct, initialize it and then return one of its fields. The order of evaluation is guaranteed to be the order of the initializers (edit: This might not be true. Discuss it on reddit).

This is the core technique which in general allows us to store and return temporary data in a macro.

swap

The fst primitive lets us write the dreaded swap macro very easily, without any temporary variables.

#define swap(x, y)         \
    ((void)((x) = fst((y), \
                      (y) = (x))))

In action:

int main(void) {
    char *x = "first", *y = "second";
    swap(x, y);
    printf("%s %s\n", x, y);
    return 0;
}

Result: (with an online compiler, if you don't believe me!)

second first

Further uses

In C we have to clean up our resources manually. I often find myself wanting to directly return the result of some string operation, only to have to put that in a temporary before cleaning up the string itself.

Let's say a function constructs and prints a string, returning how many characters it printed.

    char* str = malloc(...);
    ...
    int tmp = printf("<a format involving %s>", str);
    free(str);
    return tmp;

This can be transformed to:

    char* str = malloc(...);
    ...
    return fst(printf("<a format involving %s>", str),
               free(str));

Portability notes

__typeof__ is an extension from GCC and Clang, and maybe more. You could avoid it by passing the type name(s) to the macro, or using some devious sizeof magic.

Apart from that, compound literals are standard C99. They're even supported by MSVC.

  1. The comma operator evaluates its operands in order, and returns the second. What I mean by the complement of the comma operator is this. In designing what the comma operator does, there were two choices: return the first or the second. The comma chooses the second, `fst` chooses the first.