Search code examples
ccastingundefined-behavior

Is this cast of void pointer valid code or vile code?


Is this valid/proper code, or does it violate standards -- possibly invoking undefined behavior (UB)?

--> Specifically, the cast of void * to char ** in foo(). <--

It does work, but we know that 'working' isn't good enough.

And any other errors, please rip it up and post corrected code if you like, please.

#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

void foo(void *vp)
{
    char **dp = (char **)vp;
    int i;

    for(i=0; i<SIZE; i++)
    {
        printf("%s", dp[i]);
    }
}

int main()
{
    char **dp;
    int i;

    dp = malloc(SIZE * sizeof(char *));
    for(i=0; i<SIZE; i++)
    {
        dp[i]= malloc(20);
        sprintf(dp[i],"Now: %d\n",i);
    }
    foo(dp);

    return 0;
}

Output:

Now: 0
Now: 1
Now: 2
Now: 3
Now: 4

I tried foo(void **vp) which seems right to me but does not compile. Conversely, foo(void *vp) seems wrong(?) but compiles and works. I've not been concerned with trivialities like this until now, as I am wanting to take my C to the next level.


Solution

  • A void * is essentially a generic pointer type. Any object pointer type, regardless of how many "levels" that pointer is, may be converted to a void * and back without a cast.

    Because of this, the conversion from void * to char ** is not only safe but the cast is unnecessary.

    Trying to use void ** doesn't work because the special treatment given to void * doesn't carry over to a void **. A void ** is a specific type: a pointer to a void *.