Re: We've got i++, why not a "post-assignment" operator ?



"sha0.miller@xxxxxxxxx" <sha0.miller@xxxxxxxxx> writes:

Ben Bacarisse wrote:
<snip>
[...] SWAP might be a macro, but a generic SWAP macro is not
without it problems.
<snip>
The 'SWAP_STMNT()' below is one reason why I thought a standardized

'typeof' construct might be handy.

#include <stdio.h>

/* Internal. */
#define SWAP_BUDDY(ident) \
swap_buddy_ ## ident

/* Internal. */
#define SWAP_TYPE(ident) \
swap_type_ ## ident

/**
* Establish 'ident' for use with 'SWAP()' and 'SWAP_STMNT()'.
* This is a declaration and belongs wherever declarations are allowed.
*/
#define DECL_SWAPPABLE(ident, type) \
type SWAP_BUDDY(ident); typedef type SWAP_TYPE(ident)

/* Swap 'x' and 'y' via 'tmp', return 'x'. */
#define SWAP_TMP(tmp, x, y) \
(((tmp) = (x)), ((x) = (y)), ((y) = (tmp)))

/* Swap 'x' and 'y', return 'x'. Requires 'DECL_SWAPPABLE(x)'. */
#define SWAP(x, y) \
(SWAP_TMP(SWAP_BUDDY(x), x, y))

/* A statement which swaps 'x' and 'y'. Requires 'DECL_SWAPPABLE(x)'. */
#define SWAP_STMNT(x, y) \
do { \
SWAP_TYPE(x) swap_stmnt_tmp = (x); \
(x) = (y); \
(y) = swap_stmnt_tmp; \
} while (0)

int main(void) {
int x = 3, y = 5;
DECL_SWAPPABLE(x, int);
DECL_SWAPPABLE(y, int);
double d = 3.3, e = 5.5;
DECL_SWAPPABLE(d, double);
DECL_SWAPPABLE(e, double);

/* Initial swap for 'int's via swap statement. */
if (1)
SWAP_STMNT(x, y);
else
SWAP_STMNT(y, x);
/* Restore via swap statement. */
SWAP_STMNT(x, y);

/* Swap 'int's via swap expression. */
if ((SWAP(x, y), 1) && x == 5 && y == 3)
puts("Success for 'int'.");
else
puts("Failure for 'int'.");

/* Initial swap for 'double's via swap statement. */
if (1)
SWAP_STMNT(d, e);
else
SWAP_STMNT(e, d);
/* Restore via swap statement. */
SWAP_STMNT(d, e);

/* Swap 'double's via swap expression. */
if ((SWAP(d, e), 1) && d == 5.5 && e == 3.3)
puts("Success for 'double'.");
else
puts("Failure for 'double'.");

return 0;
}

I am not sure this is worth the effort. It seems only able to swap
objects named by simple identifiers -- no SWAP(a[i], a[j]) or
SWAP(a.one, a.two).

I'd do this:

#define SWAP(a, b) \
do { char temp[sizeof (a)]; \
memcpy(temp, &(a), sizeof (a)); \
memcpy(&(a), &(b), sizeof (a)); \
memcpy(&(b), temp, sizeof (a)); \
} while (0)

and hope that memcpy is special-cased for small objects. I think it is
in gcc for example.

--
Ben.
.