void 指针笔记

2021-12-24 14:24:05 浏览数 (4)

void 指针笔记

void 指针

void指针可以用来保存所有数据类型的地址(即,通用指针),例如:

代码语言:javascript复制
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

代码语言:javascript复制
// 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;
}

其实就是用一个临时变量保存要复制的数据,然后再把数据复制到目标地址上。

参考

  1. StackOverflow: What is a void pointer and what is a null pointer?
  2. 10.20 — Void pointers
  3. void pointer in C / C
  4. Write your own memcpy() and memmove()

1 人点赞