0

How does one edit void pointers? Obviously, this is possible in C, because there are many standard library functions that do this.

I thought I'd implement a function swapping two array elements (I know there is a standard function for it, it's just an exercise), so ideally I'd want to do this:

void swap(void *arr, int a, int b, int elSize) {
    void arrEl = arr[a];
    arr[a] = arr[b];
    arr[b] = arrEl;
}

Of course, I can't dereference a void pointer, nor can I have a variable of type void, so I have to work around that somehow, but I discovered I don't know how to edit a void type array.
So how should I implement above pseudo-C?

I saw this thread, but I am not sure how to apply that and think seeing the correct version of above pseudo-C will make it a bit more clear.

4
  • Why you declared arrEl as void? Commented Nov 17, 2013 at 14:51
  • @haccks How do you mean? I know it is invalid C, but please read the last paragraph. Commented Nov 17, 2013 at 14:52
  • @haccks And what if I'd want to pass in a struct to this function? If this were a 'real' function I'd have to write another function like this, only with different types. I just wanted to learn about void pointers and then came across this. Commented Nov 17, 2013 at 14:58
  • You can pass struct (its address) to your function as arr is of void * type. Commented Nov 17, 2013 at 15:11

3 Answers 3

1

Technically you can't have a void array or void values. You can have a void pointer that points to an array of some type.

To use it you have to cast it to a non-void pointer, like e.g.

int value0 = ((int *) arr)[0];

And the simplest solution to not have to do this is to declare the pointer arr as a pointer to the type it actually is.

If you can't do that, then if you have the element size, you can declare temporary variable-length arrays to handle the swapping, like

char tmp[elSize];

memcpy(tmp, (char *) arr + elSize * a, elSize);
memcpy((char *) arr + elSize * a, (char *) arr + elSize * b, elSize);
memcpy((char *) arr + elSize * b, tmp, elSize);

The above swaps between the values at "index" a and b.

Sign up to request clarification or add additional context in comments.

4 Comments

But say elSize > sizeof(int), wouldn't I swap only part of a possibly large struct, thus corrupting the passed in array?
Thank you for the updates. One last question: is this temporary array trick considered 'standard'?
@11684 It's standard in C.
I'd use char* or unsigned char*, not uint8_t*. Presumably elSize is intended to be the size in bytes, which by definition is the size of a char. (It's possible to have CHAR_BIT > 8; in that case, uint8_t won't exist.)
1

Joachim was a bit faster, but I'll add my answer anyway.

#include <string.h>

void swap(void *arr, size_t a, size_t b, size_t elSize) {
    char temp[elSize];

    memcpy(temp, (char*)arr+a*elSize, elSize);
    memcpy((char*)arr+a*elSize, (char*)arr+b*elSize, elSize);
    memcpy((char*)arr+b*elSize, temp, elSize);
}

#include <stdio.h>
int main(void)
{

int array[3] = {1,13,42};

char text[] = "This is text\n" ;

swap(text, 0, 2, 4);

printf("%s", text );

swap(array, 0, 2, sizeof array[0] );

printf("{%d %d %d}\n", array[0], array[1], array[2] );

return 0;
}

2 Comments

Is there any difference between using char and uint8_t at all (except the first is obviously easier to type)?
There will probably be a difference on machines with CHAR_BIT unequal to 8. (these are rare today for general purpose machines, but some DSP's have 16 or 32 bit chars, IIRC) BTW: I don't expect these machines to have uint8_t defined. In any case: the smallest adressable unit of memory is char. (and therefore sizeof (char) is 1)
0

By assigning arr[a] to arrEl, in fact you are dereferencing a void type pointer. And for this you must have to cast it before doing any operation to it. As;

int arrEl = ((int *)arr)[a];  

or

int arrEl = *((int *)arr + a); 

1 Comment

If you knew int was the right type, you wouldn't need to use void* in the first place, and you wouldn't need to pass elSize. memcpy is almost certainly the right solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.