0

I am implementing a generic sort in C according to an assignment. In this assignment I need to get and sort (in bubble sort) an array of type void. The function signature is: void bubbleSort(void* arrayToSort,int lenArray,size_t sizeElements, int (*compare)(const void*,const void*)) I got a peroblem: I find this error "expression must be a pointer to a complete object type" almost in everything I am doing. I searched, but all the advises about this error are to cast it first to the real type. I can't cast it, because the function is ment to be generic, and all I know is the size of the array's type. Can someone help me? This is the code:

void bubbleSort(void* arrayToSort,int lenArray,size_t sizeElements, int (*compare)(const void*, const void*)) {
    bool didExcanged = false;
    for (int i = 0; i < lenArray && (!didExcanged); i++)
    {
        void* pivot = arrayToSort + i * sizeElements;//that error on "arrayToSort"
        didExcanged = false;
        for (int j = i; j < lenArray; j++)
        {
            void* toCompare = arrayToSort + j * sizeElements;//that error on "arrayToSort"
            if (compare(pivot,toCompare)>0) {
                swap(pivot, toCompare);
                didExcanged = true;
            }
        }
    }
}

and the swap function:

void swap(void* a, void* b) {
    void *temp=*a;//that error on "*a"
    *a = *b;//that error on "*a" and "*b" 
    *b = *temp;//that error on "*b" and "*temp"
}
ns120
  • 3
  • 1
  • 1
    You cannot access the data where a `void*` points to. There is no known size to it. Just as with your compare function you need to cast to a specific type before accessing it. Or you can just use `memcpy` to transfer `sizeElements` bytes. – Gerhardh Aug 31 '20 at 09:24
  • Also see this related q: [C - fastest method to swap two memory blocks of equal size](https://stackoverflow.com/questions/37329329/c-fastest-method-to-swap-two-memory-blocks-of-equal-size-solution-feasibilit) – rustyx Aug 31 '20 at 09:50

2 Answers2

1

You can't de-reference a void*, because the void type doesn't have a size - it's an incomplete type hence the warning "must be a complete object type".

You can't write a generic swap function based on void* without knowing the size of the data objects, so you must pass that information along to swap.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

void* is a weird one in C. It is technically a pointer, but it also differs from other pointer types in that it cannot be de-referenced. Nor can you do pointer arithmetic on it. You can store and retrieve any pointer type in it, but you cannot do anything with it other than store it or typecast it into another type. In your situation, the only viable approach seems to be the one that a memcpy implementation would use - typecast it to an unsigned char * which is guaranteed to be de-referenceable for any type.

Example:

void my_memcpy(void* a, void* b, size_t size)
{
    unsigned char *p = (unsigned char*)a;
    unsigned char *q = (unsigned char*)b;
    while(size--)
    {
        *p++ = *q++;
    }
}

A swap can be implemented using memcpy as:

void swap(void* a, void* b, size_t size)
{
    unsigned char temp[size];
    memcpy(temp, a, size);
    memcpy(a, b, size);
    memcpy(b, temp, size);
}
th33lf
  • 2,177
  • 11
  • 15