Why gnulib uses `*(void **) ptrptr` instead of proper, and without cast, usage - c

I came across int safe_alloc_realloc_n (void *ptrptr, size_t size, size_t count) function, at Github/scratchpadRepos/gnulib, which is actually an older version of the official gnulib,
In that function, I found *(void **)ptrptr weird,
With or without the cast, it contains a memory address, so is there any point of casting here,

Why gnulib uses *(void **) ptrptr instead of proper, and without cast, usage
The argument is a void *, doing *ptrptr would try to assign to void. void is a void, you can't assign to it.
On POSIX systems you can cheat, all pointers have the same alignment and size. You can do int *a; *(void **)&a = some_value;, although such code is very invalid according to C language.
The function takes a generic pointer void * and then assigns to the pointer, so that you can int *a; safe_alloc_realloc_c(&a, ...) pass a pointer to any pointer type. Otherwise you would have to create a separate function for every type safe_alloc_realloc_c_int(int **, ...) safe_alloc_realloc_c_char(char **, ...) etc.
Have same functionality,
No. malloc allocates memory. new allocates the memory and creates an object, calling object constructor and starting object lifetime.

Related

Are void * pointers meant for generic typing in C?

I often see void pointers being cast back and forth with other types of pointers and wonder why, I see that malloc() returns a void pointer that needs to be cast before used also.
I am very new to C and come from Python so pointers are a very new concept to wrap my head around.
Is the purpose of the void * pointer to offer some "dynamic" typing?
Take this code as example, is it valid code?
struct GenericStruct{
void *ptr;
};
// use void pointer to store an arbitrary type?
void store(struct GenericStruct *strct, int *myarr){
strct->ptr = (void *) myarr;
}
// use void pointer to load an arbitrary type as int*?
int *load(struct GenericStruct *strct){
return (int *) strct->ptr;
}
The purpose of a void * is to provide a welcome exception to some of C's typing rules. With the exception of void *, you cannot assign a pointer value of one type to an object of a different pointer type without a cast - for example, you cannot write
int p = 10;
double *q = &p; // BZZT - cannot assign an int * value to a double *
When assigning to pointers of different types, you have to explicitly cast to the target type:
int p = 10;
double *q = (double *) &p; // convert the pointer to p to the right type before assigning to q
except for a void *:
int p = 10;
void *q = &p; // no cast required here.
In the old days of K&R C, char * was used as a "generic" pointer type1 - the memory allocation functions malloc/calloc/realloc all returned char *, the callback functions for qsort and bsearch took char * arguments, etc., but because you couldn't directly assign different pointer types, you had to add an explicit cast (if the target wasn't a char *, anyway):
int *mem = (int *) malloc( N * sizeof *mem );
Using explicit casts everywhere was a bit painful.
The 1989/1990 standard (C89/C90) introduced the void data type - it's a data type that cannot store any values. An expression of type void is evaluated only for its side effects (if any)2. A special rule was created for the void * type such that a value of that type can be assigned to/from any other pointer type without need of an explicit cast, which made it the new "generic" pointer type. malloc/calloc/realloc were all changed to return void *, qsort and bsearch callbacks now take void * arguments instead of char *, and now things are a bit cleaner:
int *mem = malloc( sizeof *mem * N );
You cannot dereference a void * - in our example above, where q has type void *, we cannot get at the value of p without a cast:
printf( "p = %d\n", *(int *)q );
Note that C++ is different in this regard - C++ does not treat void * specially, and requires an explicit cast to assign to different pointer types. That's because C++ provides overloading mechanisms that C doesn't.
Every object type should be mappable to an array of char.
In K&R C, all functions had to return a value - if you didn't explicitly type the function, the compiler assumed it returned int. This made it difficult to determine which functions were actually meant to return a value vs. functions that only had side effects. The void type was handy for typing functions that weren't meant to return a value.
C suffers from the absence of function overloading. So most C "generic" functions as for example qsort or bsearch use pointers to void * that to be able to deal with objects of different types.
In C you need not to cast a pointer of any type to a pointer of the type void *. And a pointer of any type can be assigned with a pointer of the type void * without casting.
So in C the functions from your code snippet can be rewritten like
void store(struct GenericStruct *strct, int *myarr){
strct->ptr = myarr;
}
int *load(struct GenericStruct *strct){
return strct->ptr;
}
Is the purpose of the void * pointer to offer some "dynamic" typing?
No, because C has no dynamic typing. But your title is about right, on the other hand -- void * serves roughly as a generic pointer type, in the sense that a pointer of that type can point to an object of any type. But there is no dynamism as that term is usually applied in this sort of context, because values of type void * do not contain any information about the type of object to which they point.
The use, then, is for pointers where the type of the object pointed to does not matter (for a given purpose). In some cases the size of the pointed-to object does matter, however, so that is sometimes provided alongside such pointers. The standard qsort() function is a canonical example. In other cases, such as generic linked lists, it is up to the user to know, somehow, what type of object is pointed to.
As #Vlad already observed, however, casting between void * and other object pointer types is not required in C. Such conversions are performed automatically upon assignment, and in other contexts that use the same rules as assignment.

Assigning the value from the void pointer to a non void pointer

I have a situation where in the address inside the void pointer to be copied to a another pointer. Doing this without a type cast gives no warnings or errors. The pseudo code looks like
structA A;
void * p = &A;
structA * B = p;// Would like to conform this step
I don't foresee any problems with this.
But since this operation is used over a lot of places, I would like to conform whether it can have any replications. Also is there any compiler dependency?
No, this is fine and 100% standard.
A void * can be converted to and from any other data/object pointer without problems.
Note that data/object restriction: function pointers do not convert to/from void *.
This is the reason why you shouldn't cast the return value of malloc(), which returns a void *.
In C a void * is implicitly compatible with any pointer. That why you don't need to cast when e.g. passing pointers of any type to functions taking void * arguments, or when assigning to pointer (still of any type) from function returning void * (here malloc is a good example).

Why memcpy is using void pointer as parameter?

would it be OK if the function was: void memcpy(char* dst, const char* src, size_t size)?
What is the advantage of using void pointers in memcpy()?
Before the void data type was added in the 1989 standard, that was how functions like memcpy were designed. char * was the closest thing to a "generic" pointer at the time.
The problem is that if memcpy still used char * arguments and you wanted to call memcpy on a target that wasn't an array of char, you would have to explicitly cast the pointer value:
int foo[N];
int bar[N];
...
memcpy( (char *) foo, (const char *) bar, N * sizeof *foo );
because you can't assign pointers of one type to another type without a cast. This wasn't (as much of) a problem in pre-ANSI C because you didn't have function prototypes; that is, the compiler didn't check that the number and types of arguments in the function call matched the definition, but it's definitely an issue now.
However, unlike other object pointer types, you can assign any T * value to void * and back again without needing the cast, so the memcpy call can be written as
memcpy( foo, bar, N * sizeof *foo );
I remember the pre-standardization days (although I was still in college). Casting gymnastics weren't fun. Embrace the void * type, because it is saving you some heartburn.
would it be OK if the function was: void memcpy(char* dst, const char* src, size_t size)?
Yes, because pointers can be casted to another pointer type.
What is the advantage of using void pointer in memcpy()?
Avoiding a cast to the destination pointer type.
What is the advantage of using void pointer in memcpy()?
A void pointer is a generic pointer, so it can accept a pointer to any type.

What is the intention/benefit of malloc returning type void *?

Knowing more C++ than C I wondered if someone could explain the reason why malloc() always returns a pointer of type void, rather than malloc having been implemented with some mechanism which allows it to return a pointer of the type the user passed in? It just seems a little "hacky" constantly explicitly casting the returned void pointer to the type you want.
Well, in C you don't have to do the cast, so your point is moot. That is, these two statements are 100% equivalent:
char *x = malloc(100);
char *y = (char *)malloc(100);
Conversions to and from void * are implicit in C. So, to address your question, the very reason malloc returns void * is so that you don't have to cast.
Besides that, in C there's no way to pass type information around, so doing something like:
char *x = malloc(100, char);
is not possible.
If you're in C++, the cast is necessary, but you shouldn't be using malloc anyway - that's what new is for, and it does handle the type information correctly.
It's not hacky at all, from C standard ISO/IEC 9899 2011, section 6.2.2.3:
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
So a pointer to void* is a valid pointer to whatever type you want without the need of explicit casting.
In addition to this you can't dynamically pass a type to a function to let so that it will return the correct type, you can pass just the size itself (so malloc would be able to allocate size_t count * size_t size but not return the correctly type in any case).
C has no mechanism for "passing a type" at all. Also, in C, conversion from void* to a pointer of any other type is automatic (no cast is needed) so malloc works naturally in C. It's only in C++ where malloc requires casts to work.
There are two reasons, first, malloc doesn't know why you need memory. So it just return number of bytes asked to return. Secondly you cannot de-reference void * easily so it can help you to avoid accidents.
int *p;
p = (int *)malloc(sizeof(int)*10);

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

I have seen a function whose prototype is:
int myfunc(void** ppt)
This function is called in a C file as
a = myfunc(mystruct **var1);
where mystruct is typedef for one of structure we have.
This works without any compilation errors in MSVC6.0, But when I compile it with some other C compiler, it gives an error at the place where this function is called with error message:
Argument of type mystruct ** is incompatible with parameter of type void **
The argument of myfunc() is kept as void** because it seems to be a generic malloc kind of function to be called with various structure variable types for memory allocation
Is there any type such as void ** allowed in C standard/any C compilers?
How do I fix this? [I tried casting the function call argument to mystruct**, but it didn't work]
-AD
The comp.lang.c FAQ addresses this issue in detail in Question 4.9. In short, they say it's not strictly portable to cast an arbitrary pointer-to-pointer to a void **; they go on to explain that "code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal)." They go on to explain that "any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want)."
So, you can safely/portably achieve the desired behavior with code like:
some_type *var1 = foo();
void *tmp_void_ptr = (void *)var1;
myfunc(&tmp_void_ptr);
void** is valid but, based on your error message, you probably have to explicitly cast the argument as follows:
mystruct **var1;
x = myfunc ((void**) var1);
That's because the myfunc function is expecting the void** type. While void* can be implicitly cast to any other pointer, that is not so for the double pointer - you need to explicitly cast it.
There is a reason the compiler cannot automatically cast 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 the implicit cast from myotherstruct* to void* in the *x = *b line, even though that line is trying to put a pointer to a myotherstruct in a place where only pointers to mystruct should be put.
The mistake is in fact in the previous line, which is converting "a pointer to a place where pointers to mystruct can be put" to "a pointer to a place where pointers to anything can be put". This is the reason there is no implicit cast. Of course, when you use a explicit cast, the compiler assumes you know what you are doing.
This question is slightly confusing. But yes, void ** is certainly legal and valid C, and means "pointer to pointer to void" as expected.
I'm not sure about your example of a call, the arguments ("mystruct **var1") don't make sense. If var1 is of type mystruct **, the call should just read a = func(var1);, this might be a typo.
Casting should work, but you need to cast to void **, since that is what the function expects.
As dirty as it may look like: sometimes you can't solve a problem without using void **.
Yes, void ** is perfectly acceptable and quite useful in certain circumstances. Also consider that given the declaration void **foo and void *bar, the 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 on a few ancient platforms you needn't worry about), but it will not know the size of the object pointed to by bar (it could point to an object of any size). You can therefore safely perform pointer arithmetic on void ** pointers but not on void * pointers. You must cast them to something else first, like a char *. GCC will allow you to pretend that void * and char * are equivalent, each pointing to an object a single byte in size, but this is nonstandard and nonportable.

Resources