Detailed explanation and application of void* in C language

Void is interpreted as a noun in English as "emptiness; space; gap"; and in C language, void is translated as "no type", and the corresponding void * is "untyped pointer". Void seems to have only the role of "comment" and restricting the program. Of course, the "comment" here is not to provide comments for us, but to provide a so-called comment for the compiler.

The address of this article: http://www.cnblogs.com/archimedes/p/c-void-point.html, please indicate the source address for reprinting.

The role of void:
1. The limitation of function return, this situation is more common for us.

2. The limitation of function parameters, this situation is also relatively common.

In general, these two situations are common:

When the function does not need to return a value, it must be qualified with void, which is what we call the first case. For example: void func (int a, char *b).

When the function is not allowed to accept parameters, you must use void qualification, which is what we call the second case. For example: int func(void).

Rules for the use of void pointers:
1. A void pointer can point to any type of data, that is to say, any type of pointer can be used to assign a value to a void pointer. E.g:

  int *a;

  void *p;

  p=a;

If you want to assign void pointer p to pointers of other types, you need to cast, in this case: a=(int *)p. In the memory allocation, we can see the use of void pointers: the pointer returned by the memory allocation function malloc is void *. When the user uses this pointer, he must perform a forced type conversion, that is, explicitly indicate the memory pointed to by the pointer. What type of data is stored in (int ) malloc(1024) means that it is mandatory to store int data in the memory pointed to by the void pointer returned by malloc .

2. In the ANSI C standard, some arithmetic operations on void pointers such as p++ or p+=1 are not allowed, because since void is untyped, we don’t know how many bytes to operate on each arithmetic operation, such as char The type operates on sizeof (char) bytes, while int has to operate on sizeof (int) bytes. In GNU, it is allowed, because by default, GNU considers void * to be the same as char *. Since it is certain, some arithmetic operations can of course be performed, where sizeof(*p)==sizeof(char).

Void almost only has the function of "commenting" and restricting the program, because no one has ever defined a void variable, let us try to define:

void a;

When this line of statement is compiled, an error will occur, prompting "illegal use of type'void'". Even if the compilation of void a does not make an error, it has no practical meaning.

As we all know, if the pointers p1 and p2 are of the same type, then we can directly assign values ​​between p1 and p2; if p1 and p2 point to different data types, we must use the cast operator to convert the pointer type on the right side of the assignment operator Is the type of the left pointer.

 float *p1;
 int *p2;
 p1 = p2;

//The p1 = p2 statement will compile error,
// prompt "'=': cannot convert from'int *'to'float *'", must be changed to:
p1 = (float *)p2;
and void * is different , Any type of pointer can be directly assigned to it, without coercion

void *p1;
int *p2;
p1 = p2;

But this does not mean that void * can also be assigned to pointers of other types without casting. Because "no type" can contain "typed", and "typed" cannot contain "no type".

Be careful with void pointer types:

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:错误
pvoid += 1; //ANSI:错误

//The reason why the ANSI standard recognizes this is because it insists: the pointer for arithmetic operations must be sure to know the size of the data type it points to.
//E.g:

int *pint;
pint++; //ANSI:正确

The result of pint++ is to increase sizeof(int).
But GNU does not think so, it specifies the arithmetic operation of void * is consistent with char *. Therefore, the following statements are all correct in the GNU compiler:

pvoid++; //GNU:正确
pvoid += 1; //GNU:正确

The execution result of pvoid++ is that it has increased by 1.
In the actual program design, in order to meet the ANSI standard and improve the portability of the program, we can write the code to achieve the same function as follows:

void * pvoid;
((char *)pvoid)++; //ANSI:错误;GNU:正确
(char *)pvoid += 1; //ANSI:错误;GNU:正确

There are some differences between GNU and ANSI. Generally speaking, GNU is more "open" than ANSI and provides more syntax support. But when we are designing in real life, we should still cater to ANSI standards as much as possible. If the parameters of the function can be pointers of any type, then the parameters should be declared as void *

Note: The void pointer can be any type of data, which can bring us some benefits in the program. When the function is a pointer type, we can define it as a void pointer, so that the function can accept any type of pointer. Such as:

The function prototypes of typical memory operation functions memcpy and memset are:

void * memcpy(void *dest, const void *src, size_t len);
void * memset ( void * buffer, int c, size_t num );

In this way, any type of pointer can be passed into memcpy and memset, which truly reflects the meaning of the memory operation function, because the object it operates on is only a piece of memory, regardless of the type of memory (see C language implementation Generic programming). If the parameter type of memcpy and memset is not void *, but char *, that's really weird! Such memcpy and memset are obviously not a "pure, out of low-level fun" function! The appearance of void is just for an abstract need. If you correctly understand the concept of "abstract base class" in object-oriented, it is easy to understand the void data type. Just as we can't define an instance for an abstract base class, we can't define a void (let us call void an "abstract data type" analogously) variable.

Reprinted from: https://www.cnblogs.com/wuyudong/p/c-void-point.html

Guess you like

Origin blog.csdn.net/weixin_42692164/article/details/113616383