C++ void指针的用法(非常详细)
C++ 是一种强类型语言,其中的变量都有自己的数据类型,用于保存相应类型的数据。
例如,一个 int 类型的变量可以保存数值 1,而不能保存数值 1.1,后者需要一个 double 类型的变量来保存。
虽然相应数据类型的变量保存相应的数据本来是相安无事的,但在 C++ 中却出现了一个异类,那就是 void 类型。
从本质上讲,void 类型并不是一个真正的数据类型,我们不能定义一个 void 类型的变量。void 更多的是一种抽象和占位符号。在程序中,void 类型主要用于“修饰”和“限制”一个函数。
例如,如果一个函数没有返回值,则可用 void 作为这个函数的返回值类型;如果一个函数没有形式参数列表,也可用 void 作为其形式参数,表示该函数不需要任何参数。
与 void 类型对函数的“修饰”作用不同,void 类型指针作为指向抽象数据的指针,可以成为不同类型指针之间转换的桥梁。
众所周知,把一个指针赋值给另一个指针时,如果两个指针的类型相同,那么可以直接在这两个指针之间进行赋值;如果指针的类型不同,则必须使用强制类型转换,把赋值操作符右边的指针类型转换为左边的指针类型,然后才能进行赋值。
例如:
但是,当使用 void 类型的指针时,就不需要进行类型转换了。void 类型的指针具有很大的灵活性,任何其他类型的指针都可以直接赋值给 void 类型的指针,例如:
虽然任何类型的指针都可以直接赋值给 void 类型的指针,但这并不意味着 void 类型的指针可以直接赋值给其他类型的指针。要完成这个赋值,必须经过强制类型转换,把“无类型”转换为“有类型”。例如:
例如,把 int 类型的指针赋值给 void 类型的指针,那么这个 void 类型的指针指向的就是 int 类型的数据。如果随后再把这个 void 类型的指针强制转换成 double 类型的指针并尝试通过它访问所指向的数据,就很可能得到错误的结果。因为 void 类型的指针不要求指向特定的数据类型,所以它可以用来代表任何类型的指针,如果函数可以接受任何类型的指针,那么应该将其参数声明为 void 类型的指针。
例如,以下是一个内存复制函数的声明:
如果 memcpy() 函数的参数类型不是 void 类型的指针,而是 char 类型的指针或者其他类型的指针,那么在使用其他类型的指针作为参数调用 memcpy() 函数时,就需要进行指针类型的转换以匹配其参数类型的要求,以符合具体数据的数据类型,这样一来,memcpy() 函数就不能视为一个“纯粹的、脱离低级趣味的”内存复制函数。
例如,一个 int 类型的变量可以保存数值 1,而不能保存数值 1.1,后者需要一个 double 类型的变量来保存。
虽然相应数据类型的变量保存相应的数据本来是相安无事的,但在 C++ 中却出现了一个异类,那就是 void 类型。
从本质上讲,void 类型并不是一个真正的数据类型,我们不能定义一个 void 类型的变量。void 更多的是一种抽象和占位符号。在程序中,void 类型主要用于“修饰”和“限制”一个函数。
例如,如果一个函数没有返回值,则可用 void 作为这个函数的返回值类型;如果一个函数没有形式参数列表,也可用 void 作为其形式参数,表示该函数不需要任何参数。
与 void 类型对函数的“修饰”作用不同,void 类型指针作为指向抽象数据的指针,可以成为不同类型指针之间转换的桥梁。
众所周知,把一个指针赋值给另一个指针时,如果两个指针的类型相同,那么可以直接在这两个指针之间进行赋值;如果指针的类型不同,则必须使用强制类型转换,把赋值操作符右边的指针类型转换为左边的指针类型,然后才能进行赋值。
例如:
int* pInt; // 指向整数的指针 float* pFloat; // 指向浮点数的指针 pInt = pFloat; // 直接赋值会产生编译错误 pInt = (int*)pFloat; // 强制类型转换后进行赋值
但是,当使用 void 类型的指针时,就不需要进行类型转换了。void 类型的指针具有很大的灵活性,任何其他类型的指针都可以直接赋值给 void 类型的指针,例如:
void* pVoid; // void类型的指针 pVoid = pInt; // 任何其他类型的指针都可以直接赋值给void类型的指针 pVoid = pFloat;
虽然任何类型的指针都可以直接赋值给 void 类型的指针,但这并不意味着 void 类型的指针可以直接赋值给其他类型的指针。要完成这个赋值,必须经过强制类型转换,把“无类型”转换为“有类型”。例如:
pInt = (int*)pVoid; // 通过强制类型转换,将void类型的指针转换成int类型的指针 pFloat = (float*)pVoid; // 通过强制类型转换,将void类型的指针转换成float类型的指针虽然通过强制类型转换,void 类型的指针可以在其他类型的指针之间自由转换,但这种转换应当遵循一定的规则,void 类型的指针所转换成的其他类型的指针,必须与它所指向的数据类型相符。
例如,把 int 类型的指针赋值给 void 类型的指针,那么这个 void 类型的指针指向的就是 int 类型的数据。如果随后再把这个 void 类型的指针强制转换成 double 类型的指针并尝试通过它访问所指向的数据,就很可能得到错误的结果。因为 void 类型的指针不要求指向特定的数据类型,所以它可以用来代表任何类型的指针,如果函数可以接受任何类型的指针,那么应该将其参数声明为 void 类型的指针。
例如,以下是一个内存复制函数的声明:
void* memcpy(void* dest, const void* src, size_t len);在这里,任何类型的指针都可以作为参数传入 memcpy() 函数中。这真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一块内存,而不关心这块内存中存储的数据是什么数据类型。
如果 memcpy() 函数的参数类型不是 void 类型的指针,而是 char 类型的指针或者其他类型的指针,那么在使用其他类型的指针作为参数调用 memcpy() 函数时,就需要进行指针类型的转换以匹配其参数类型的要求,以符合具体数据的数据类型,这样一来,memcpy() 函数就不能视为一个“纯粹的、脱离低级趣味的”内存复制函数。