Замена указателей не приводит к изменению указанных значений. Если бы это было так, это было бы похоже на смену адресных этикеток на конвертах, которые перенесли бы меня в ваш дом, а вы - в мой.
Вы были почти там:
void swap(void *a, void *b, size_t size) {
char temp[size]; // C99, use malloc otherwise
// char serves as the type for "generic" byte arrays
memcpy(temp, b, size);
memcpy(b, a, size);
memcpy(a, temp, size);
}
Функция memcpy копирует память, которая является определением объектов в C. (Вызывается POD или обычные данные в C ++, для сравнения.) Таким образом, memcpy - это то, как вы делаете назначение без заботясь о типе объекта, и вы могли бы вместо этого написать другие назначения как memcpy:
int a = 42, b = 3, temp;
temp = b;
b = a;
a = temp;
// same as:
memcpy(&temp, &b, sizeof a);
memcpy(&b, &a, sizeof a);
memcpy(&a, &temp, sizeof a);
Это именно то, что делает вышеуказанная функция, поскольку вы не можете использовать присваивание, когда вы не знаете тип объекта, а void - это тип, который заменяет «неизвестный». (Это также означает «ничего», когда используется как тип возвращаемого значения функции.)
В качестве любопытства, еще одна версия, которая избегает malloc в обычных случаях и не использует VLA C99:
void swap(void *a, void *b, size_t size) {
enum { threshold = 100 };
if (size <= threshold) {
char temp[threshold];
memcpy(temp, b, size);
memcpy(b, a, size);
memcpy(a, temp, size);
}
else {
void* temp = malloc(size);
assert(temp); // better error checking desired in non-example code
memcpy(temp, b, size);
memcpy(b, a, size);
memcpy(a, temp, size);
free(temp);
}
}