tags:

views:

465

answers:

5

I have an array that contains pointers. How can I swap two pointers - say array[1] and array[4] - correctly?

+3  A: 

You need a temporary variable:

void*temp = array[4];
array[4]=array[1];
array[1] = temp;

Edit Fixed first line.

martinr
Why is `void` the type?
Pieter
Line 1 should be array[4], no?
ezod
Your code is wrong, just a confusion of array indexes.It's copying array[1] to temp, then overwriting array[4] and putting temp back in to array[1].
Tony
Void is only a pointer, without actually specifing a datatype.
Pindatjuh
In your code it would be whatever the type of the array is.If you have int* array[N], where N is some size, or int** array, where array points at an array held elsewhere, it would be int*.
martinr
@Tony Yuh. Code fixed now.
martinr
@Pieter, the type is `void *`, i.e., pointer to `void`. The C standard guarantees that any object pointer can be converted to `void *` and back—thus, making above independent of the type of pointers inside `array`.
Alok
+5  A: 
void* temp = array[1]; 
array[1] = array[4]; 
array[4] = temp;
Tony
A: 

My C is quite rusty, but a simple

int* foo = array[4]; array[4] = array[1]; array[1] = foo;

should suffice.

dbemerlin
+3  A: 

The most correct way is using a temporary variable as in :

void *tmp_pointer;

....
tmp_pointer = array[1];
array[1] = array[4];
array[4] = tmp_pointer;
....

Stay away from any evil bit or int hacks! :)

Let me add here that we should have asked "what type of pointer?"

In theory, you can't safely mix pointers to data and pointers to function. The C standard does not guarantee that this would be meaningful or possible at all. It only ensures that:

  • data pointers can be converted back and from void *
  • ((void *)0) is a pointer that is different from any data pointer or function pointer
  • function pointers of one type can be converted to function pointers of another type and back.

I understand that this is because in some architecture, the address space for data is completely separated from the address space for functions and you can't safely convert from on type of pointers to the other and back.

Remo.D
Aw, but that means no xor-swap... :P
JPvdMerwe
I imagined someone would suggest that. If they didn't already, someone will! It's too evil :)
Remo.D
+1  A: 
#include <stdint.h>
if (1 != 4) {
    array[1] = (void*)((intptr_t)(array[1]) ^ (intptr_t)(array[4]));
    array[4] = (void*)((intptr_t)(array[1]) ^ (intptr_t)(array[4]));
    array[1] = (void*)((intptr_t)(array[1]) ^ (intptr_t)(array[4]));
}

Is much clearer and saves a temporary. ;-)

Richard Pennington
Though you need to check that 1 != 4 or else you leak memory, by nulling a pointer.
JPvdMerwe
@JP: Absolutely correct.
Richard Pennington
Tempted to give you -1 for "much clearer" which is obviously wrong. But the answer works so I'll refrain from downvoting. :-)
Graeme Perrow
I knew! Evil is all around :)
Remo.D
@Graeme, I suspect it was ironic. See the smile?
Remo.D
@JP: Is the check really required? If both are equal, then the three steps will be: array[1] = 0; array[4] = array[4]; array[1] = array[4], which will make everything okay... or am I missing something?
Johan
@Johan: no, he's saying that the code wouldn't work if it were called to swap `array[1]` with `array[1]`.
Stephen Canon
@Johan: JP was right. My edit was wrong. It just isn't need in this case because 1 != 4 usually.
Richard Pennington
"usually", huh?
Stephen Canon
@Stephen: See http://stackoverflow.com/questions/1995113/strangest-language-feature/1995476#1995476 ;-)
Richard Pennington