Detailed Explanation and Application of void* in C Language
Classification Programming Techniques
In English, "void" as a noun means "emptiness, space, gap", and in the C language, "void" is translated as "untyped", and the corresponding void *
is "untyped pointer".
Void seems to only serve as a "comment" and to restrict the program; of course, this "comment" is not for us humans but for the compiler to provide a so-called comment.
The Role of void
It restricts the return of a function, which is a common situation.
It restricts the parameters of a function, which is also a common situation.
The two common situations we often see are:
When a function does not need to return a value, it must be restricted by void, which is the first situation we mentioned. For example: void func(int a, char *b).
When a function does not accept any parameters, it must be restricted by void, which is the second situation we mentioned. For example: int func(void).
The Usage Rules of void Pointers
- A void pointer can point to any type of data, which means that any type of pointer can be assigned to a void pointer. For example:
int *a; void *p; p = a;
If you want to assign the void pointer p to another type of pointer, you need to perform a forced type conversion, in this case: a = (int *)p
. We can see the use of void pointers in memory allocation: the pointer returned by the memory allocation function malloc is of type void *
. When users use this pointer, they need to perform a forced type conversion, that is, explicitly state what type of data is stored in the memory pointed to by the pointer (int *)malloc(1024)
means that the returned void* pointer by malloc points to a memory that stores int type data.
- In the ANSI C standard, it is not allowed to perform some arithmetic operations on void pointers, such as p++ or p+=1, because since void is untyped, we don't know how many bytes to operate on each time, for example, char type operates sizeof(char) bytes, while int needs to operate sizeof(int) bytes. However, GNU allows it because, by default, GNU considers
void *
to be the same aschar *
, and since it is determined, of course, some arithmetic operations can be performed, heresizeof(*p) == sizeof(char)
.
Void almost only serves as a "comment" and to restrict the program because no one has ever defined a void variable. Let's try to define it:
void a;
This line of code will cause a compilation error, indicating "illegal use of type 'void'". Even if void a
does not cause a compilation error, it has no practical significance.
As we all know, if the types of pointers p1 and p2 are the same, we can directly assign between p1 and p2; if p1 and p2 point to different data types, we must use a forced type conversion operator to convert the type of the pointer on the right side of the assignment operator to the type of the pointer on the left side.
float *p1;
int *p2;
p1 = p2;
// The statement p1 = p2 will cause a compilation error,
// indicating “'=' : cannot convert from 'int *' to 'float *'”, it must be changed to:
p1 = (float *)p2;
However, void *
is different; any type of pointer can be directly assigned to it without forced type conversion.
void *p1;
int *p2;
p1 = p2;
But this does not mean that void *
can also be assigned to other types of pointers without forced type conversion. Because "untyped" can accommodate "typed", while "typed" cannot accommodate "untyped".
Be careful when using the void pointer type:
According to the ANSI (American National Standards Institute) standard, you cannot perform arithmetic operations on void pointers, that is, the following operations are illegal:
void *pvoid;
pvoid++; //ANSI: Error
pvoid += 1; //ANSI: Error
// The reason why the ANSI standard is determined this way is that it insists: the pointer performing arithmetic operations must be determined to know the size of the data type it points to.
// For example:
int *pint;
pint++; //ANSI: Correct
However, GNU does not agree with this, it specifies that the arithmetic operations of void *
are consistent with `