Is void ** an acceptable type in ANSI-C?

I saw a function whose prototype is:

int myfunc(void** ppt) 

This function is called in the C file as a = myfunc (mystruct ** var1);

where mystruct is a typedef for one of the structure we have.

This works without compilation errors in MSVC6.0. But when I compile it with some other C compiler, it gives an error in the place where this function is called with an error message:

The argument of type mystruct ** is incompatible with the parameter of type void **

Myfunc () is saved as void ** because it is a generic type of malloc function that must be called with various types of structure variables to allocate memory

  • Is there any type like void ** allowed in C-standard / any C compiler?
  • How to fix it? [I tried to include the function call argument in mystruct** , but that didn't work]

-AD

+6
c void
source share
6 answers

void** valid, but based on your error message, you probably should explicitly specify the argument as follows:

 mystruct **var1; x = myfunc ((void**) var1); 

This is because the myfunc function expects type void** . While void* can be implicitly applied to any other pointer, this is not the case for a double pointer - you need to use it explicitly.

+9
source share

The comp.lang.c FAQ addresses this issue in detail in Question 4.9 . In short, they say do not strictly wrap an arbitrary pointer to a pointer to void ** ; they continue to explain that "such code can work and is sometimes recommended, but it relies on all types of pointers having the same internal representation (which is common, but not universal)." They further explain that "any void ** value you play with must be the address of the actual void * value somewhere other than (void **)&dp , although they may close the compiler, they are intolerable (and may not even be do what you want).

This way you can safely / portable achieve the desired behavior with code, for example:

 some_type *var1 = foo(); void *tmp_void_ptr = (void *)var1; myfunc(&tmp_void_ptr); 
+20
source share

There is a reason that the compiler cannot automatically drop from mystruct** to void** .

Consider the following code:

 void stupid(struct mystruct **a, struct myotherstruct **b) { void **x = (void **)a; *x = *b; } 

The compiler will not complain about an implicit myotherstruct* from myotherstruct* to void* on the *x = *b , although this line tries to put the pointer to myotherstruct in the place where only the pointers to mystruct .

The error is actually in the previous line, which converts "a pointer to a place where pointers to mystruct can be placed" to "a pointer to a place where pointers to anything can be placed". It is for this reason that there is no implicit throw. Of course, when you use an explicit cast, the compiler assumes that you know what you are doing.

+3
source share

This question is a bit confusing. But yes, void ** is certainly legal and valid C and means "pointer to a pointer to void ", as expected.

I'm not sure about your call example, the arguments ("mystruct ** var1") do not make sense. If var1 is of type mystruct ** , the call should just read a = func(var1); It could be a typo.

Casting should work, but you need to use void ** as this is what the function expects.

+1
source share

How dirty it may look: sometimes you cannot solve the problem without using void **.

0
source share

Yes, void ** is quite acceptable and very useful in certain circumstances. Also keep in mind that given the declaration void **foo and void *bar compiler will know the size of the object pointed to by foo (it points to a pointer, and all pointers are the same size, except for a few ancient platforms that you don't need) t worry), but he will not know the size of the object that the bar points to (he can point to an object of any size). Therefore, you can safely perform pointer arithmetic on void ** pointers, but not on void * pointers. You must first transfer them to something else, such as char * . GCC allows you to pretend that void * and char * equivalent, each of which points to the same byte size, but it is non-standard and not portable.

0
source share

All Articles