tags:

views:

132

answers:

4

Hi. I have the compiler complaining (warning) about the folowing.

Am I missing something? Because I thought this didn't need a cast

char* CurrentCh  = some ptr value;
int size;

size = func(&CurrentCh);

with func defined like this

int func(void** ptr);

Compiler warning:

passing argument 1 of 'func' from incompatible pointer type

Thx

+6  A: 

In C you can pass any pointer type to a function that expects a void*. What it says is "I need a pointer to something, it doesn't matter what it points to". Whereas void** says "I need a pointer to a void*, not a pointer to another pointer type".

Ferruccio
Correct, your function declaration is asking specifically for a 'pointer to void', not for 'pointer to pointer to void'. If you change that to func(void* ptr) it should work correctly. I do have to wonder why you want a pointer to a pointer, unless it's an array of pointers.
Chris S
Because I want ptr to be a "return parameter": I expect CurrentCh to point to something else after the call. I am doing it wrong.(note that my real function already has a return parameter).
matkas
then you need just one pointer, and will have to cast it to the desired type too.
scooterman
+1  A: 

In C, any pointer can downcast to void*, but not to void**. You will need an explicit cast.

Joel
+3  A: 

In C, void * is the generic pointer type. But void ** is not a generic pointer-to-pointer type! If you want to be able to pass a pointer to a pointer in a generic way, you should use void * anyway:

#include <stdio.h>

void func(void *ptr)
{
    char **actual = ptr;
    const char *data = *actual;
    printf("%s\n", data);
}

int main(void)
{
    char *test = "Hello, world";
    func(&test);
    return 0;
}
Alok
ok but but then it is not clear in the "func" definition that is assuming ptr to be a return parameter, isn't it?
matkas
@matkas: Yes, you have a choice of either doing what I did, or declaring `func()` as `func(char **ptr)`.
Alok
+2  A: 

The cast is necessary as what you do is a form of type punning: You reinterpret the memory which is pointed to from char * to void *.

For these types, the C standard guarantees that this actually works as char * and void * have the same representation. For other type combinations, this may not be the case.

The relevant parts of the standard are section 6.2.5, §27

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.

and less relevant (but perhaps also interesting) section 6.3.2.3, §7

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

Anything beyond that is implementation-specific.

Christoph