void *意味着什么以及如何使用它?

时间:2012-07-24 08:15:02

标签: c

今天当我阅读别人的代码时,我看到了类似void *func(void* i);的内容,这里void*分别代表函数名和变量类的含义是什么?

另外,我们何时需要使用这种指针以及如何使用它?

11 个答案:

答案 0 :(得分:157)

指向void的指针是“通用”指针类型。可以将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);

数组表达式iArrdArrlArr被隐式地从数组类型转换为函数调用中的指针类型,并且每个都隐式地从“指针转换为{{1 }} / int / double“指向long”的指针。

比较函数看起来像:

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。在编译时没有办法解决这个问题;你只需要一个错误的阵列。

答案 1 :(得分:22)

使用void *意味着该函数可以采用不需要特定类型的指针。 例如,在套接字函数中,您有

send(void * pData, int nLength)

这意味着您可以通过多种方式调用它,例如

char * data = "blah";
send(data, strlen(data));

POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));

答案 2 :(得分:6)

在这方面,C是值得注意的。我们可以说 虚无是虚无 void *就是一切(可以是每个人)

只是这个微小的*才能与众不同。

雷恩指出了这一点。 void *是指向某个位置的指针。有什么“解释”是留给用户的。

这是在C中使用不透明类型的唯一方法。可以在glib或通用数据结构库中找到非常突出的示例。它在“C接口和实现”中得到了非常详细的处理。

我建议你阅读完整的章节并尝试理解指向“获取它”的指针。

答案 3 :(得分:3)

void*

是一个'指向内存的指针,没有假设存储了什么类型'。 例如,您可以使用如果要将参数传递给函数,并且此参数可以是多种类型,并且在函数中您将处理每种类型。

答案 4 :(得分:3)

您可以查看有关指针http://www.cplusplus.com/doc/tutorial/pointers/的本文,并阅读章节:无效指针

这也适用于C语言。

  

指针的void类型是一种特殊类型的指针。在C ++中,无效   表示缺少类型,因此void指针是指针   指向没有类型的值(因此也是未确定的   长度和未确定的解引用属性)。

     

这允许void指针从整数指向任何数据类型   value或浮点到字符串。但作为交换,他们有   一个很大的限制:他们指出的数据不能直接   dereferenced(这是合乎逻辑的,因为我们没有要取消引用的类型   由于这个原因,我们总是要把地址输入   void指针指向一个指向具体的其他指针类型   解除引用之前的数据类型。

答案 5 :(得分:3)

void指针称为通用指针。我想用一个示例pthread场景来解释。

线程函数将原型设为

void *(*start_routine)(void*)

pthread API设计者考虑了线程函数的参数和返回值。如果那些东西是通用的,我们可以在作为参数发送时输入强制转换为void *。类似地,可以从void *中检索返回值(但我从未使用过线程函数的返回值)。

void *PrintHello(void *threadid)
{
   long tid;

   // ***Arg sent in main is retrieved   ***
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      //*** t will be type cast to void* and send as argument.
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);   
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }    
   /* Last thing that main() should do */
   pthread_exit(NULL);
}

答案 6 :(得分:1)

void*是一个指针,但它指向的类型是未指定的。当您将void指针传递给函数时,您需要知道它的类型是什么,以便稍后在函数中将其强制转换为正确的类型以使用它。您将看到pthreads中的示例,这些示例使用的函数与示例中用作线程函数的原型完全相同。然后,您可以使用void*参数作为指向您选择的通用数据类型的指针,然后将其强制转换为该类型以在您的线程函数中使用。在使用void指针时你需要小心,除非你回到它的真实类型的指针,你最终会遇到各种各样的问题。

答案 7 :(得分:1)

C11标准(n1570)§6.2.2.3al1p55说:

  

指向void的指针可以转换为指向任何对象的指针   类型。指向任何对象类型的指针可以转换为指向   无效又回来;结果应与原始数据相等   指针。

您可以使用此通用指针存储指向任何对象类型的指针,但您不能使用它的常规算术运算,并且您不能将它推迟。

答案 8 :(得分:0)

该函数接受一个指向任意类型的指针并返回一个这样的。

答案 9 :(得分:-1)

它表示指针可以使用此链接获取有关指针的更多信息 http://www.cprogramming.com/tutorial/c/lesson6.html

答案 10 :(得分:-6)

函数名之前的VOID表示它不返回任何内容。只是做一些事情。另一方面,作为参数的VOID使其成为可以接受任何类型参数的通用函数。但是你必须提供具有this参数大小的函数。