指针中的Void *有什么用

时间:2018-07-25 05:50:30

标签: c++ pointers

我无法理解此指针代码中(void *)的使用。

std::cout<< "address character = " << (void *) &givenChar<<"\n\n";

4 个答案:

答案 0 :(得分:4)

首先,您需要知道地址运算符&的作用。对于&givenChar,它返回一个指向变量givenChar的指针。假设givenCharchar类型,那么&givenChar将为char*类型。

使用格式化的输出运算符<<时,传递char*会将指针视为指向零终止字符串的第一个字符的指针,并将打印该字符串。如果要打印实际的 pointer (而不是它指向的字符串),则需要将指针转换为类型为void*的通用无类型指针。

这就是cast的原因:为了能够打印指向字符的实际指针。

答案 1 :(得分:2)

您未告知我们givenChar是什么类型。根据名称,它必须为char。在这种情况下,表达式&givenChar的类型为char*。如果按原样使用它,那么将选择参数类型为const char*的重载流运算符,该运算符将被视为指向以C空终止的字符串的指针。这是不正确的,因为&givenChar是指向单个字符的指针,并导致未定义的行为。表达式(void *) &givenChar强制编译器选择参数类型为const void*的重载流运算符,该运算符将打印指针中包含的地址。

答案 2 :(得分:1)

无效指针只是存储任何内存地址的变量。指针值只是一个内存地址。所有内存地址都是一定大小的,因此让我们有一个通用的数据类型,它可以存储任何对象的地址。

&givenChar返回变量givenChar所在的内存地址。如果变量的数据类型为char,则返回的内存地址的数据类型为char*。然后,我们将该char*值转换为void*数据类型。然后将类型转换的结果打印到屏幕上。

如果您有一个char*值,则可以取消引用它以获得指向的char。这很容易记住:取消引用星星“ *”。但是,由于void*可以存储任何数据类型的内存地址,因此我们无法取消引用它,因为我们不知道该值以前是char*还是int*,或者甚至没有std::string*转换成void*之前。这很重要,因为不同的数据类型在内存中具有不同的大小和不同的表示形式。这就是为什么我们不能取消引用void*的原因,我们只是不知道它曾经指向什么。

答案 3 :(得分:0)

在这种情况下,需要打印字符地址,这就是为什么使用&givenChar获取givenChar地址的原因。再次将其强制转换为(void *),以便调用适当的重载来打印地址,而不将其视为char*Null终止的字符串。


此外,如果我们深入了解它,指向void的指针是一种“通用”指针类型。 void *可以转换为任何其他指针类型,而无需显式强制转换。您不能取消引用void *或对其进行指针算术;您必须先将其转换为指向完整数据类型的指针。

它用于需要在同一代码中使用不同指针类型的地方。一个经常引用的示例是库函数qsort

void qsort(void *base, size_t nmemb, size_t size, 
           int (*compar)(const void *, const void *));

base是数组的地址,nmemb是数组中元素的数量,size是每个元素的大小,compar是指针一个比较数组两个元素的函数。它的调用方式如下:

int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);

在函数调用中,数组表达式iArr, dArr, and lArr被隐式地从数组类型转换为指针类型,并且每个表达式都被隐式地从“ pointer to int/double/long”转换为“ pointer to void”。

比较功能类似于:

int compareInt(const void *lhs, const void *rhs)
{
  const int *x = lhs;  // convert void * to int * by assignment
  const int *y = rhs;

  if (*x > *y) return 1;
  if (*x == *y) return 0;
  return -1;
}

通过接受void *qsort可以使用任何类型的数组。

使用void *的缺点是您将类型安全性扔出了窗外,迎面而来。没有什么可以保护您避免使用错误的比较例程:

qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);

compareInt期望其参数指向int,但实际上正在与double使用。在编译时没有办法解决这个问题。您会发现数组排序错误。