Search code examples
carraysvoidmemcpymemmove

How to split a generic void array into parts.c


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


Solution

  • 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)