C 使用和取消引用(void**)

C 使用和取消引用(void**),c,pointers,void-pointers,pointer-to-array,C,Pointers,Void Pointers,Pointer To Array,我想传递一个指向函数的“多态”指针数组 我可以在没有警告的情况下执行以下操作: foo (void* ptr); bar() { int* x; ... foo(x); } gcc显然会自动将x强制转换为(void*),这简直太棒了 但是,当我执行以下操作时,会收到警告: foo (void** ptr); bar() { int** x; // an array of pointers to int arrays ... foo(x); } note: expe

我想传递一个指向函数的“多态”指针数组

我可以在没有警告的情况下执行以下操作:

foo (void* ptr);

bar()
{
  int* x;
  ...
  foo(x);
}
gcc显然会自动将
x
强制转换为
(void*)
,这简直太棒了

但是,当我执行以下操作时,会收到警告:

foo (void** ptr);

bar()
{
  int** x; // an array of pointers to int arrays
  ...
  foo(x);
}

note: expected ‘void **’ but argument is of type ‘int **’
warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
我的问题是:为什么将
(int*)
作为
(void*)
参数传递不是“不兼容”,而是将
(int**)
作为
(void**)
参数传递

由于所有指针类型的大小都相同(对吗?我已经有一段时间没有使用C了), 我仍然可以这样做:

void mainFunc1(int** arr, int len)
{
    //goal is to apply baz to every int array
    foo(baz, arr, len);
}

void mainFunc2(double** arr, int len)
{
    //goal is to apply baz to every int array
    foo(qux, arr, len);
}

// I PROMISE that if I pass in a (int**) as ptr, then funcPtr will interpret its (void*) argument as an (int*)
void foo(funcPtr f, void** ptr, int len)
{
    for(int i = 0; i < len; i++)
    {
        f(ptr[i]);
    }
}

void baz(void* x) 
{
  int* y = (int*)x;
  ...
}

void qux(void* x)
{
  double* y = (double*)x;
  ...
}
void mainFunc1(整数**arr,整数len)
{
//目标是将baz应用于每个int数组
foo(baz、arr、len);
}
void mainFunc2(双**arr,int len)
{
//目标是将baz应用于每个int数组
foo(qux、arr、len);
}
//我保证,如果我将(int**)作为ptr传递,那么funcPtr将把它的(void*)参数解释为(int*)
无效foo(函数f,无效**ptr,整数)
{
对于(int i=0;i

所有空指针的用途是,我可以使用一个函数指针应用于具有不同类型的ptr参数的函数(从栈的底部):一些函数将采用
int
数组,一些函数将采用
double
数组,等等。

因为C中没有指向指针类型的通用指针


参考资料:

注意:
void*
是通用的。但是
void**
不是。您可以将任何类型的地址分配给
void*
变量,但
void**
只能分配给
void*
变量的地址

void* generic;
int i;
int *ptri = &i;

generic = ptri;

有效,但以下是一个错误:

void**  not_generic;
int i;
int *ptri = &i;
int **ptr_to_ptr1 = &ptri;
void**  not_generic = ptr_to_ptr1;
错误:将
int**
分配给
void**

是的,你可以这样做:

void**  not_generic;
not_generic = &generic;
对于通用数组函数,只需按如下方式使用
void*a

enum {INT, CHAR, FLOAT};
void print_array(void* a, int length, int type){
   int i = 0;
   for(i = 0; i < length; i++){
      switch(type){
         case INT: 
              printf("%d", *((int*)a + i));
              break;
         case CHAR: 
              printf("%c", *((char*)a + i));
              break;
         case FLOAT: 
              printf("%f", *((float*)a + i));
              break;
      }
   }
}
假设
char

 char a[] = {'1', '2', '3', '4'}; 
 print_array(a, sizeof(a)/sizeof(a[0]), CHAR);

简单的回答是:任何类似于

<datatype>* <variable_name>
*

可以在参数声明类型为void*的位置传递,因为void*是泛型的。然而,void**不是。所以自动转换失败。

看到了吗?你到底为什么要使用void?你不必这么做?我有一个通用函数(上面的foo),我试图避免重复,因为它比foo复杂一些。它应该有一个列表列表和一个应用于每个列表的函数指针。mainFunc只是一个例子。为什么模板不起作用?哦,别介意,我看你没有把它标记为C++。主要是因为我以前从来没有用过C++,没有理由我不能,如果那样会使工作变得更容易。
 char a[] = {'1', '2', '3', '4'}; 
 print_array(a, sizeof(a)/sizeof(a[0]), CHAR);
<datatype>* <variable_name>