1

as a beginner in C, I am struggling with an obscure problem and because I couldn't find a solution to this particular problem I want to ask you the following: Currently I am trying to understand void pointers and their arithmetic operations. I attempted to write a generic function, which accepts a void pointer to an array, the length of the array and size of one element and splits the given array into two different parts (list1 and list2):

void split(void *array, int arrlen, int objsize)
{
// divide the arrlen and save the values
    int len_list1 = arrlen / 2;
    int len_list2 = arrlen - len_list1;

// Allocate memory for two temporary lists
    void *list1 = (void*)malloc(objsize * len_list1);
    void *list2 = (void*)malloc(objsize * len_list2);

    if (list1 == NULL || list2 == NULL)
    {
        printf("[ERROR]!\n");
        exit(-1);
    }

// list1 gets initialized properly with int and char elements
    memmove(list1, array, len_list1*objsize);           
    printf("list1:"); 
    print_arr(list1, len_list1);

// memmove((char*)list2, (char*)array+list_1_length, list_2_length*objsize); (*)
    memmove(list2, (int*)array+len_list1, len_list2*objsize);
    printf("list2:");
    print_arr(list2, len_list2);
}

My problem is the following: If I give this function an int array it will work fine, but if I call split() with a char array as an argument, I have to...

memmove((char*)list2, (char*)array+list_1_length, list_2_length*objsize);
//memmove((int*)list2, (char*)array+list_1_length, list_2_length*objsize);

comment line (*) out, in order to have the same results. A solution certainly could be to write an if-else condition and test the objsize:

if (objsize == sizeof(int))
    // move memory as in the 1st code snippet
else
    // move memory with the (int*) cast

But with this solution I would also have to check other data types, so it would be very kind of you to give me a hint.

Thanks!

-matzui

matzui
  • 17
  • 3
  • As additional information for readers, there are a few other serious flaws in your snippet. Firstly, C has no garbage collection of any kind so you **must** use `free` on `list1` and `list2` after you're done with them. Also, `memmove` can come handy but as you're copying data to memory blocks that have just been allocated, you have the guarantee that `array`, `list1` and `list2` will not overlap hence you should use `memcpy` (from `string.h`) here. Please consider my edit to your post. – dummydev May 29 '15 at 15:34

2 Answers2

3
memmove(list2, (int*)array+len_list1, len_list2*objsize);

Here you typecast array to an int *, and add len_list1 to it. But adding something to a pointer, means it will be multiplied with the size of one element of the datatype of that pointer. So if an int is 4 bytes, and you add 5 to an int * variable, it will move 20 bytes.

Because you know exactly how many bytes you want to move the pointer, you can cast is to char * (char = 1 byte), and add the number of bytes to it.

So instead of (int*)array+len_list1, you can use (char*)array+(len_list1*objsize)

wimh
  • 15,072
  • 6
  • 47
  • 98
1

A void pointer is just a word-sized dereferencable pointer that implies no particular data type. Thus, you cannot do pointer math with it. To do what you're trying to do, declare an appropriately typed pointer in your function, and then set its value equal to that of the parameter void pointer.

Curt
  • 5,518
  • 1
  • 21
  • 35
  • What do you mean with "appropriately typed pointer"? Do you thought of sth like void *tmp = (char*)array + i*objsize to access the i-th element? – matzui Jan 24 '15 at 22:02