In English, void as a noun is defined as"emptiness, space, gap", and in C language, void is translated as"no type", correspondinglyvoid * is"typeless pointer"。
void seems to only serve as a "comment" and to restrict the program. Of course, the "comment" here is not for us humans, but a so-called comment provided to the compiler.
The Role of void
1. Restricting function return values; this is a common case.
2. Restricting function parameters; this is also quite common.
Generally, these are the two cases we often see:
- When a function does not need a return value, void must be used to restrict it. This is the first case we mentioned. For example: void func(int a, char *b).
- When a function is not allowed to accept parameters, void must be used to restrict it. This is the second case we mentioned. For example: int func(void).
Rules for Using void Pointers
1. A void pointer can point to data of any type, that is, 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 a pointer of another type, you need a type cast. In this case:a=(int *)pIn memory allocation, we can see the use of void pointers: the pointer returned by the memory allocation function malloc isvoid *type. When using this pointer, the user must perform a type cast, that is, explicitly specify what type of data is stored in the memory pointed to by the pointer.(int *)malloc(1024)It means explicitly specifying that the memory pointed to by the void* pointer returned by malloc stores int data one by one.
2. In the ANSI C standard, arithmetic operations on void pointers, such as p++ or p+=1, are not allowed, because since void has no type, we do not know how many bytes each arithmetic operation should operate on. For example, char type operates on sizeof(char) bytes, while int needs to operate on sizeof(int) bytes. In GNU, however, it is allowed, because by default, GNU considersvoid *andchar *them to be the same. Since it is definite, arithmetic operations can certainly be performed. Heresizeof(*p)==sizeof(char)。
void almost only serves as a "comment" and to restrict the program, because no one ever defines a void variable. Let's try to define one:
void a;
This line will cause a compile error, with the message"illegal use of type 'void'"Even ifvoid acompiling it does not error, it has no practical meaning.
As we all know, if pointers p1 and p2 are of the same type, then we can directly assign between p1 and p2; if p1 and p2 point to different data types, we must use the type cast operator to convert the pointer type on the right side of the assignment operator to the type of the pointer on the left.
float *p1; int *p2; p1 = p2; //其中p1 = p2语句会编译出错, //提示“'=' : cannot convert from 'int *' to 'float *'”,必须改为: p1 = (float *)p2;
andvoid *But void* is different; any type of pointer can be directly assigned to it without a type cast.
void *p1; int *p2; p1 = p2;
But this does not mean thatvoid *it can also be assigned to pointers of other types without a type cast. Because "no type" can accommodate "typed", but "typed" cannot accommodate "no type".
Be careful with void pointer types:
According to the ANSI (American National Standards Institute) standard, arithmetic operations on void pointers are not allowed; that is, the following operations are all illegal:
void * pvoid; pvoid++; //ANSI:错误 pvoid += 1; //ANSI:错误 //ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。 //例如: int *pint; pint++; //ANSI:正确The result of pint++ is to increase it by sizeof(int).
But GNU does not see it that way; it specifiesvoid *that the arithmetic operations ofchar *are consistent. Therefore the following statements are all correct in GNU compilers:
pvoid++; //GNU:正确 pvoid += 1; //GNU:正确
The result of executing pvoid++ is that it increases by 1.
In actual programming, to comply with the ANSI standard and improve program portability, we can write code that implements the same functionality as follows:
void * pvoid; ((char *)pvoid)++; //ANSI:错误;GNU:正确 (char *)pvoid += 1; //ANSI:错误;GNU:正确
GNU and ANSI also have some differences. Overall, GNU is more "open" than ANSI and provides support for more syntax. But in real design, we should still try to conform to the ANSI standard as much as possible. If a function's parameter can be a pointer of any type, then its parameter should be declared asvoid *。
Note:A void pointer can point to data of any type, which can bring us some benefits in programs. When a function parameter is a pointer type, we can define it as a void pointer, so that the function can accept pointers of any type. For example:
Typical examples are the function prototypes of the memory operation functions memcpy and memset, respectively:
void * memcpy(void *dest, const void *src, size_t len); void * memset ( void * buffer, int c, size_t num );
In this way, pointers of any type can be passed to memcpy and memset. This truly reflects the meaning of memory operation functions, because the object they operate on is only a piece of memory, regardless of what type the memory is (see C Language Implementation of Generic Programming). If the parameter types of memcpy and memset were notvoid *, butchar *that would be truly strange! Such memcpy and memset are obviously not "pure, refined" functions! The emergence of void is only for the need of abstraction. If you correctly understand the concept of "abstract base class" in object-oriented programming, it is also easy to understand the void data type. Just as you cannot define an instance of an abstract base class, we also cannot define a void variable (let us analogically call void an "abstract data type").
Original URL: https://www.cnblogs.com/wuyudong/p/c-void-point.html