C++如何对void指针进行解引用?将int指针转换为void指针。

3
这些代码显示如下错误:
int e = 5, * ePtr = &e;
void * vPtr = ePtr; 
cout << *vPtr; 

语法错误:

`void*'不是指向对象类型的指针

我知道:

  1. 任何指针类型都可以在没有显式转换的情况下存储在void指针类型中
  2. 对void指针进行解引用尝试是语法错误

但是如果我们不能执行点#2,那么除了在语法上正确之外,点#1有什么用处呢?我想使用vPtr打印5(即此处的e)..是否可能?

这个运行良好:

int e = 5, * ePtr = &e;
void * vPtr = ePtr; //specific to generic Ok!
double * dPtr = (double *)vPtr; //to let compiler know stoarge size
cout << *dPtr; //indirectly it is vPtr i.e. a void ptr, can be deref only if cast

4
void *主要用于存储任何指针,以便您可以将其转换回正确的类型并使用它。这更多地是C风格编码的方式。 - chris
尝试使用强制类型转换 void * vPtr = (void*)ePtr; - ahmedsafan86
@Ahmedsafan,你需要使用反引号:\void vPtr = (void)ePtr;`` - chris
6个回答

5

为了解除 void* 指针的引用,您需要将指针强制转换回兼容类型。

void*指针在C中经常使用,但是,在C++中我们可以进行函数重载和多态性,因此它们的使用更加有限。

在C中使用void*指针的一个很好的例子是使用回调的函数:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
                   void *(*start_routine) (void *), void *arg);

当您调用pthread_create函数时,它会回调您的start_routine函数。在这种情况下,您可能想要将一些数据传递给您的start_routine函数。由于线程库无法为您希望传递给回调的每种类型声明一个pthread_create函数,因此使用void*类型代替。请注意,html标签已保留,不做改动。
void myCallBack(void* arg) {
   int* value = (int*)arg;

   /* Do something with value: it is an int* now*/
   printf("Message from callback %d\n", *value);
}


/* Some main function or whatever... */
{ 
  /*  ... */
  int foo = 123;
  ret = pthread_create(&thread, &attr,myCallBack, &foo);

  /*  ... */
}

4

void*可以指向任何东西,因此将任何指针分配给它都是完全可以的。

但是由于它可能指向任何东西,因此无法对其进行解引用:编译器不知道它指向哪种对象类型,因此无法生成根据对象类型执行正确操作的代码。


3

你不能对它进行解引用,因为编译器不知道它是什么。你必须将其转换为适当的类型(并且编译器必须假设您知道自己在做什么)。

void *指针最好用于在相当低的级别(例如I/O驱动程序)与东西进行交互时,您很少关心正在处理的数据,只知道您有一个缓冲区和大小。

任何其他用途都充满危险。例如

int i = 5;
void *p = &i;
.....
float *f = (float *)p;

这段代码不会引起编译器报错或警告,它是完全有效的。但它可能不会按照您期望的方式执行。


2

在设计纯C的存储容器(如链表、哈希表)时,存储指针并保持对其类型的不确定性是有用的。这就是void*的作用。如果您想要使用指针,则必须跟踪其类型和值,因为您不能随意地推迟指针,并且当您将其转换为void*时,所有类型信息都会丢失。

在您的示例中,您可以使用一个简单的结构,其中包含一个void*和一个类型字段。

在C++中,您可以通过多态结构甚至模板来实现这些功能:您正在做的事情更像是C风格。


1
您不能使用void*而不进行类型转换来打印e。指针不仅是一个简单的变量,它存储地址,还具有指示编译器应该读取多少大小的类型。 void*没有任何类型,因此无法进行解引用操作。通过类型转换,您告诉编译器从指针所携带的地址开始应该读取多少字节。 void*为程序员提供了一种轻松的方式来存储和使用其他类型的指针。我们不能使用unsigned int或类似类型来存储指针的值,因为指针的大小取决于处理器。此外,我们可以使用void*使函数的指针参数/返回值更加通用。

raj raj:这不是真的,执行“void * vPtr = (int *)ePtr; cout << *vPtr;”会生成相同的错误。因此,一旦声明了指针的void类型,它就永远无法被解引用。 - ShivaniDhanked
我的意思是,我们可以将void*强制转换为其实际类型后解引用它。 - raj raj

0

我认为您想要将int指针存储到void*指针中。 在这种情况下,可能会出现警告,例如“将整数强制转换为不同大小的指针”。 因此,您首先需要分配一些与整数相关的void指针内存,然后可以像下面这样使用该void指针:

void *ptr = malloc(sizeof(int));
*((int*)ptr) = 5;
printf("%d\n",*((int*)ptr));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接