What Is a Void Pointer in C++

What is a void pointer in C++?

A void* does not mean anything. It is a pointer, but the type that it points to is not known.

It's not that it can return "anything". A function that returns a void* generally is doing one of the following:

  • It is dealing in unformatted memory. This is what operator new and malloc return: a pointer to a block of memory of a certain size. Since the memory does not have a type (because it does not have a properly constructed object in it yet), it is typeless. IE: void.
  • It is an opaque handle; it references a created object without naming a specific type. Code that does this is generally poorly formed, since this is better done by forward declaring a struct/class and simply not providing a public definition for it. Because then, at least it has a real type.
  • It returns a pointer to storage that contains an object of a known type. However, that API is used to deal with objects of a wide variety of types, so the exact type that a particular call returns cannot be known at compile time. Therefore, there will be some documentation explaining when it stores which kinds of objects, and therefore which type you can safely cast it to.

This construct is nothing like dynamic or object in C#. Those tools actually know what the original type is; void* does not. This makes it far more dangerous than any of those, because it is very easy to get it wrong, and there's no way to ask if a particular usage is the right one.

And on a personal note, if you see code that uses void*'s "often", you should rethink what code you're looking at. void* usage, especially in C++, should be rare, used primary for dealing in raw memory.

What does void* mean and how to use it?

A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. You cannot dereference a void * or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.

void * is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort:

void qsort(void *base, size_t nmemb, size_t size, 
int (*compar)(const void *, const void *));

base is the address of an array, nmemb is the number of elements in the array, size is the size of each element, and compar is a pointer to a function that compares two elements of the array. It gets called like so:

int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);

The array expressions iArr, dArr, and lArr are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int/double/long" to "pointer to void".

The comparison functions would look something like:

int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;

if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}

By accepting void *, qsort can work with arrays of any type.

The disadvantage of using void * is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:

qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);

compareInt is expecting its arguments to be pointing to ints, but is actually working with doubles. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.

Why does a void pointer point to anything?

A void pointer is a pointer to anything. It is a generic pointer that doesn't have a particular type. It can also have the value NULL in which case it doesn't point to anything.
To use a void pointer, you have to keep track of what it actually points to and when you are going to use it, you must cast it to the appropriate type.

They can be dangerous, because if you cast it to the wrong type, it will result in undefined behavior at runtime.

Can we call (void *)0 a void pointer in C?

What will i call it now ? A void pointer, a null pointer or a null
void pointer ?

In this declaration

void *pointer = NULL;

there is declared a pointer of the type void * that is a null pointer due to initializing it with a null pointer constant.

A pointer to object of any type can be a null pointer.

The casting of the zero integer constant to void * is used because a pointer of the type void * can be implicitly converted to any other object pointer
type. Another advantage of using the type void * is that you may not dereference a pointer of that type because the type void is always an incomplete type.

Early versions of C did not have the type void. Instead of the type void there was used the type char. So for example in old C programs you can encounter something like the following

memcpy( ( char * )p1, ( char * )p2, n );

Passing a void* pointer and then cast in C

You are, in effect, trying to make the type of your pIn variable differ, depending on the value of the passed-in type flag. But there's no way to do that. Each variable must have exactly one type, known at compile time.

The closest you could achieve to what you're trying to do would probably be something like this:

void func(void *pSrc, float *pDst, int len, int type)
{
char *pIn = pSrc; /* char * so can do pointer arithmetic */
float *pOut = pDst;
while (len--) {
*pOut++ = (type == 0 ? *(float *)pIn : *(int *)pIn) * 2.0;

if (type == 0)
pIn += sizeof(float);
else pIn += sizeof(int);
}
}

This is kind of an ugly kludge, however. If your actual func is more complicated, it might be worth it. But if all you're doing is multiplying by 2, it would probably cleaner to just bite the bullet and use two separate functions. (Sorry, I know you said that's not what you wanted to do.)

The subexpression (type == 0 ? *(float *)pIn : *(int *)pIn) is somewhat of a jawbreaker as I've written for. (C is both celebrated, and notorious, for allowing this kind of pithiness.) You might prefer to write things out in a more "longhand" way:

void func(void *pSrc, float *pDst, int len, int type)
{
char *pIn = pSrc; /* char * so can do pointer arithmetic */
float *pOut = pDst;
while (len--) {
double inVal;

if (type == 0) {
inVal = *(float *)pIn;
pIn += sizeof(float);
} else {
inVal = *(int *)pIn;
pIn += sizeof(int);
}

*pOut++ = inVal * 2.0;
}
}

This second formulation would also make things easier and cleaner if you have more different values for type, or if you're doing more involved things with inVal.


Addendum: Here's a completely different approach. In your original problem statement, you had either an array of int, or an array of float, and you wanted to multiply every element by 2, without repeating too much code. I assume that in your actual situation, you have functions to apply that are more involved than just "multiply by 2".

If you're comfortable using function pointers, you could literally write a pair of "apply function to int" and "apply function to float" functions, with the actual do-the-work function specified separately, and exactly once. Here are the two "apply function" functions:

void apply_func_to_int(double (*func)(double), int *pSrc, float *pDst, int len)
{
for(int i = 0; i < len; i++)
pDst[i] = func(pSrc[i]);
}

void apply_func_to_float(double (*func)(double), float *pSrc, float *pDst, int len)
{
for(int i = 0; i < len; i++)
pDst[i] = func(pSrc[i]);
}

As you can see, they are very, very similar to each other — basically a copy-and-paste job — but they're both so short, the repetition isn't too objectionable.

Here is the function to apply:

double func(double x)
{
return x * 2;
}

Notice that you only have to write this function once. It accepts and returns a double, for reasonably full generality.

Putting it all together:

int main()
{
int i;
int input[3] = { 1, 2, 3 };
float output[3] = { 0 };
apply_func_to_int(func, input, output, 3);
for(i = 0; i < 3; i++) printf("%f ", output[i]); printf("\n");

float input2[3] = { 1.1, 2.2, 3.3 };
apply_func_to_float(func, input2, output, 3);
for(i = 0; i < 3; i++) printf("%f ", output[i]); printf("\n");
}

And of course you can apply other functions:

#include <math.h>

/* ... */

float input3[4] = { 2, 10, 25, 1.44 };
apply_func_to_float(sqrt, input3, output, 4);
for(i = 0; i < 4; i++) printf("%f ", output[i]); printf("\n");

How to know struct size casted to void pointer in C?

First off, having both typeX and TypeX but with very different meanings is very confusing. Also, don't hide pointers behind typedefs.

As for your question: No, you cannot recover the size of the object that t is pointing to.

sizeof EXPR gives you the size of the type of EXPR (in bytes). It does not matter what the actual value is (in fact, EXPR isn't even evaluated1).

Consider

char c;
int i;
double d[100];

TypeX p1 = (TypeX)&c, p2 = (TypeX)&i, p3 = (TypeX)d;

All of p1, p2, p3 have the same type, so sizeof will return the same value for all of them, even though the objects they're pointing to have very different sizes.

Finally, sizeof (void) is not a thing in standard C. GCC allows it as an extension (and returns 1), but it will warn you that this is non-standard if you enable -pedantic diagnostics.

1 - With one relatively obscure exception, which I'm just going to ignore.



Related Topics



Leave a reply



Submit