Jump to: navigation, search

The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 4.14 on page 91

Define a macro swap(t,x,y) that interchanges two arguments of type t . (Block structure will help.)

Solutions by Gregory Pietsch and Lars Wirzenius

Here are Greg's solutions for Cat 0 and Cat 1:

/* EXERCISE 4-14 Gregory Pietsch */

/* conditional compilation added by RJH */

#ifdef CATEGORY_0

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

#else
#ifdef CATEGORY_1

/*
This works if I can use the assignment operator on type t.
I didn't know if I was allowed to use sizeof or not and still remain
Level 0, otherwise this one is better:
*/

#define swap(t,x,y)                             do {                                                (unsigned char *)a=(unsigned char *)(&(x));     (unsigned char *)b=(unsigned char *)(&(y));     size_t i = sizeof(t);                           while (i--) {                                       *\
a ^= *b;                                       *\
b ^= *a;                                       *\
a ^= *b;                                       a\
++;                                            b\
++;                                        }    \
                                       } while (\
0)

#endif
#endif

/* editor's note: sizeof is first mentioned on p91, after this exercise,
 * and is not explained properly until p135, so it can be used in
 * [[K&R2 solutions:Ancillary:Category numbers|Category 0]] solutions only for exercises 6-1 onward.
 */






...and here is a lively entry for Category 0, from Lars, which uses token pasting to derive a name for the temporary variable:

/*
 * Solution to exercise 4-14 in K&R2, page 91:
 *
 *	Define a macro swap(t,x,y) that interchanges two arguments of type t.
 *	(Block structure will help.)
 *
 * Feel free to modify and copy, if you really must, but preferably not.
 * This is just an exercise in preprocessor mechanics, not an example of
 * how it should really be used. The trickery is not worth it to save three
 * lines of code.
 *
 * To exchange the values of two variables we need a temporary variable and
 * this one needs a name. Any name we pick, the user of the macro might also
 * use. Thus, we use the preprocessor argument concatenation operator ## to
 * create the name from the actual variable names in the call. This guarantees
 * that the result won't be either of the actual arguments. In order to
 * make sure the result also does not fall into the implementation's name
 * space, we prefix the name with something safe.
 *
 * Lars Wirzenius <liw@iki.fi>
 */

#include <stdio.h>

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

int main(void) {
	int ix, iy;
	double dx, dy;
	char *px, *py;
	
	ix = 42;
	iy = 69;
	printf("integers before swap: %d and %d\n", ix, iy);
	swap(int, ix, iy);
	printf("integers after swap: %d and %d\n", ix, iy);
	
	dx = 123.0;
	dy = 321.0;
	printf("doubles before swap: %g and %g\n", dx, dy);
	swap(double, dx, dy);
	printf("integers after swap: %g and %g\n", dx, dy);
	
	px = "hello";
	py = "world";
	printf("pointers before swap: %s and %s\n", px, py);
	swap(char *, px, py);
	printf("integers after swap: %s and %s\n", px, py);

	return 0;
}



...and here is yet another solution from Gregory:

#define swap(t,x,y)                                     \
do {                                                    \
    (unsigned char *)_0=(unsigned char *)(&(x));        \
    (unsigned char *)_1=(unsigned char *)(&(y));        \
    unsigned long _2 = (unsigned long)                  \
       ((unsigned char *)(&(x)+1)                       \
        - (unsigned char *)(&(x)));                     \
    while (_2--) {                                      \
        *_0 ^= *_1;                                     \
        *_1 ^= *_0;                                     \
        *_0 ^= *_1;                                     \
        _0++;                                           \
        _1++;                                           \
    }                                                   \
} while (0)



USER:Sammy.....Simple Category 0 Solution ;) ..Generic Programming through Macros

#define SWAP(t,x,y)  void swap(t x,t y)                                           \
                                        {t temp;                                   \
                                         temp=x;                                    \
                                         x=y;                                        \
                                         y=temp;                                      \
                                        }


Macro Call would be like this SWAP(int,x,y) SWAP(double,x,y) </b>

Personal tools
Personal tools