P99

◆ P99_SWAP

#define P99_SWAP (   _0,
  _1 
)    ((sizeof(_0) > sizeof(uintmax_t)) ? P00_SWAP1(_0, _1) : P00_SWAP2(_0, _1))

Swap the contents of the arguments.

This macro has the following properties:

  • It evaluates each of _0 and _1 only once.
  • It has a compile time check for the correct sizes.
  • It checks if the two expressions are assignment compatible in both ways
  • It has no naming issues with a hidden variable.
  • The size of the temporary variable is computed at compile time. So we may use a compound literal and not a dynamic array.
Remarks
This implementation is a follow up of a discussion on stackoverflow.
The concrete implementation separates into two different cases: P00_SWAP2(_0, _1), for small sizes, uses two temporaries in the hope that the loads into registers can be done simultaneously. The other one, P00_SWAP1(_0, _1), uses only one temporary but is then forced to serialize copy operations.
Warning
For both arguments
  • each must be an lvalue expression
  • it must be permitted to take their addresses.

So variables that have the register storage class will not work with this macro.

Warning
The types of the arguments are only checked to confirm that they have the same size and that the two lvalues are assignment compatible. If both are
  • of the same size,
  • are assignment compatible,
  • have different semantics,

you are in trouble. This may happen in the following cases:

  • A signed and unsigned type of same size, e.g signed int and unsigned int
  • Two integer types that by coincidence have the same size, e.g on a platform long and long long may both be 8 byte. This may work ok for a long time and then fail when you move to another platform.
  • If one type is a floating point type and the other an integral type, e.g double and a uint64_t may be of the same size.
  • Two types that have the same size but not the same width. A bool will usually be stored in one byte, but memcpy from a char is not equivalent to assigning it with =. Padding bits may have the effect that the value stored in a bool is a trap representation.
Remarks
argument 0 maybe evaluated several times for its type but only once for its value
argument 1 maybe evaluated several times for its type but only once for its value

Definition at line 172 of file p99_swap.h.