I know how to swap 2 variables in c++ , ie you use std::swap(a,b)
.
question:
Does the C
standard library have a similar function
Yes you need to define it yourself.
void swap(void* a, void* b, size_t length)
, but unlike std::swap
, it's not type-safe.inline
keyword).We could also define a macro like
#define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
but it shadows the ttttttttt
variable, and you need to repeat the type of a
. (In gcc there's typeof(a)
to solve this, but you still cannot SWAP(ttttttttt,anything_else);
.)
And writing a swap in place isn't that difficult either — it's just 3 simple lines of code!
You can do something similar with a macro if you don't mind using a gcc extension to the C language, typeof
:
#include <stdio.h>
#define SWAP(a, b) do { typeof(a) temp = a; a = b; b = temp; } while (0)
int main(void)
{
int a = 4, b = 5;
float x = 4.0f, y = 5.0f;
char *p1 = "Hello";
char *p2 = "World";
SWAP(a, b); // swap two ints, a and b
SWAP(x, y); // swap two floats, x and y
SWAP(p1, p2); // swap two char * pointers, p1 and p2
printf("a = %d, b = %d\n", a, b);
printf("x = %g, y = %g\n", x, y);
printf("p1 = %s, p2 = %s\n", p1, p2);
return 0;
}
Another macro not already mentioned here: You don't need to give the type if you give the temporary variable instead. Additionally the comma operator is useful here to avoid the do-while(0) trick. But usually I don't care and simply write the three commands. On the other hand a temporary macro is useful if a and b are more complex.
#define SWAP(a,b,t) ((t)=(a), (a)=(b), (b)=(t))
void mix_the_array (....)
{
int tmp;
.....
SWAP(pointer->array[counter+17], pointer->array[counter+20], tmp);
.....
}
#undef SWAP
in essence, swap function is to swap two memory block. with two addresses and the size of block in bytes, we can swap pointers, integers, doubles, arrays, structs, ...
a pointer has three parts, e.g. we can break down short* p
into three pieces
void*p
, we get a short integer.%hu
using the first two parts, we will be able to build a generic swap function:
#include<stdint.h>
#ifdef _WIN32
#define alloca _alloca
#else
#include <alloca.h>
#endif
void gswap(void * const a, void * const b, int const sz) {
// for most case, 8 bytes will be sufficient.
int64_t tmp; // equivalent to char tmp[8];
void * p;
bool needfree = false;
if (sz > sizeof(int64_t)) {
// if sz exceed 8 bytes, we allocate memory in stack with little cost.
p = alloca(sz);
if (p == NULL) {
// if sz is too large to fit in stack, we fall back to use heap.
p = malloc(sz);
//assert(p != NULL, "not enough memory");
needfree = true;
}
}
else {
p = &tmp;
}
memcpy(p, b, sz);
memcpy(b, a, sz);
memcpy(a, p, sz);
if (needfree) {
free(p);
}
}
e.g.:
{// swap int
int a = 3;
int b = 4;
printf("%d,%d\n", a, b);//3,4
gswap(&a, &b, sizeof(int));
printf("%d,%d\n", a, b);//4,3
}
{// swap int64
int64_t a = 3;
int64_t b = 4;
printf("%lld,%lld\n", a, b);//3,4
gswap(&a, &b, sizeof(int64_t));
printf("%lld,%lld\n", a, b);//4,3
}
{// swap arrays
int64_t a[2] = { 3,4 };
int64_t b[2] = { 5,6 };
printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//3,4,5,6
gswap(&a, &b, sizeof(a));
printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//5,6,3,4
}
{// swap arrays
double a[2] = { 3.,4. };
double b[2] = { 5.,6. };
printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//3.000000, 4.000000, 5.000000, 6.000000
arrswap(&a, &b, sizeof(a));
printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//5.000000, 6.000000, 3.000000, 4.000000
}
Lots of nice solutions in the other answers! Just another quick swap macro for C that I came up with when reading K&R:
#define SWAP(TYPE,x,y) TYPE a = x, x=y, y=a
In C this is often done using a macro,
there are very simplistic examples, eg:#define SWAP(type,a,b) {type _tmp=a;a=b;b=_tmp;}
... but I wouldn't recommend using them because they have some non-obvious flaws.
This is a macro written to avoid accidental errors.
#define SWAP(type, a_, b_) \
do { \
struct { type *a; type *b; type t; } SWAP; \
SWAP.a = &(a_); \
SWAP.b = &(b_); \
SWAP.t = *SWAP.a; \
*SWAP.a = *SWAP.b; \
*SWAP.b = SWAP.t; \
} while (0)
SWAP(a[i++], b[j++])
doesn't give problem side effects.SWAP
, so as not to cause bugs if a different name happens to collide with the hard-coded name chosen.memcpy
(which in fact ended up doing real function calls in my tests, even though a compiler may optimize them out).