void 指针笔记
void 指针
void
指针可以用来保存所有数据类型的地址(即,通用指针),例如:
void* test1 = new XXXClass();
int nValue;
float fValue;
struct Something
{
int nValue;
float fValue;
};
Something sValue;
void *pVoid;
pVoid = &nValue; // valid
pVoid = &fValue; // valid
pVoid = &sValue; // valid
但是和其他类型的指针不一样的地方是,void 指针不知道自己保存的地址的内容的数据类型,因此无法解引用:
代码语言:javascript复制int nValue = 5;
void *pVoid = &nValue;
cout << *pVoid <<endl; // 报错,不能解引用一个void指针
int *pInt = static_cast<int*>(pVoid); // 将void指针转换成int指针
cout << *pInt << endl; // 成功解引用
应用
例如说经常用的memcpy
,将指定范围内的数据移动到指定的内存地址。
自己的实现可以是这样的:
代码语言:javascript复制void myMemCpy(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;
// Copy contents of src[] to dest[]
for (int i=0; i<n; i )
cdest[i] = csrc[i];
}
之所以要转换成char
是因为内存地址的单位是字节。
这个问题也是面试里面经常问的,怎么实现内存拷贝函数。要注意一下,有可能会出现目标地址刚刚好就在源地址要复制的内容中间的情况,即要复制的范围和要写数据的范围重叠了,这时候就会出错。所以如果是面试题的话应该写memmov
,而不是直接答上面的memcpy
。
// A function to copy block of 'n' bytes from source
// address 'src' to destination address 'dest'.
void myMemMove(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;
// Create a temporary array to hold data of src
char *temp = new char[n];
// Copy data from csrc[] to temp[]
for (int i=0; i<n; i )
temp[i] = csrc[i];
// Copy data from temp[] to cdest[]
for (int i=0; i<n; i )
cdest[i] = temp[i];
delete [] temp;
}
其实就是用一个临时变量保存要复制的数据,然后再把数据复制到目标地址上。
参考
- StackOverflow: What is a void pointer and what is a null pointer?
- 10.20 — Void pointers
- void pointer in C / C
- Write your own memcpy() and memmove()