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.
.



Relevant Pages

  • Re: Portability regarding sizeof() function
    ... Appropriate use of sizeof is essential to writing portable code. ... The object exists even before the declaration is reached. ... Structure, union, and enumeration tags have scope that begins just ... int main ...
    (comp.lang.c)
  • Re: usage of size_t
    ... if you see the following declaration: ... sizeof() operator would return assuming the length of the array is ... The justification is that int may not be big enough to index an entire ...
    (comp.lang.c)
  • compiling kernel
    ... scripts/kconfig/qconf.h:51: error: `e' was not declared in this scope ... scripts/kconfig/qconf.h:73: error: `int updateList' redeclared as different ... scripts/kconfig/qconf.h:8: error: forward declaration of `class ConfigList' ... ConfigLineEdit' ...
    (alt.os.linux.suse)
  • DBI install problems
    ... before "bool" ... to `int' in declaration of `Perl_Gv_AMupdate' ... definition has no type or storage class ...
    (perl.dbi.users)
  • make Buildworld fails...why?
    ... type defaults to `int' in declaration of `_nc_tracing' ... data definition has no type or storage class ...
    (freebsd-questions)