Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 带有void*参数的函数原型_C_Void Pointers_Function Prototypes - Fatal编程技术网

C 带有void*参数的函数原型

C 带有void*参数的函数原型,c,void-pointers,function-prototypes,C,Void Pointers,Function Prototypes,我有两个函数,每个函数都有一个指向不同类型的指针: void processA(A *); void processB(B *); 是否有一种函数指针类型能够在不强制转换的情况下保持指向任一函数的指针? 我试着用 typedef void(*processor_t)(void*); processor_t Ps[] = {processA, processB}; 但它不起作用(编译器抱怨指针初始化不兼容) 编辑:代码的另一部分将遍历Ps的条目,而不知道类型。这段代码将以char*作为参数传递

我有两个函数,每个函数都有一个指向不同类型的指针:

void processA(A *);
void processB(B *);
是否有一种函数指针类型能够在不强制转换的情况下保持指向任一函数的指针? 我试着用

typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
但它不起作用(编译器抱怨指针初始化不兼容)

编辑:代码的另一部分将遍历Ps的条目,而不知道类型。这段代码将以char*作为参数传递。像这样:

Ps[i](data_pointers[j]);
编辑:谢谢大家。最后,我可能会使用以下内容:

void processA(void*);
void processB(void*);

typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};

...

void processA(void *arg)
{
  A *data = arg;
  ...
}
如果您
typedef void(*processor_t)()然后这将在C中编译。这是因为空参数列表将参数的数量和类型留给未指定的函数,因此此typedef只定义了一种类型,即“指向返回void的函数的指针,接受未指定类型的未指定数量的参数。”


编辑:顺便说一下,在初始值设定项列表中,函数名前面不需要符号。在C语言中,该上下文中的函数名会衰减为指向该函数的指针。

如果您强制转换它们,它会起作用

processor_t Ps[] = {(processor_t)processA, (processor_t)processB};

顺便说一句,如果您的代码中充斥着这种类型的东西,并且到处都是
开关
,以确定需要调用哪个函数,那么您可能需要看看面向对象编程。我个人不太喜欢它(尤其是C++…),但它确实能很好地去除这种带有虚拟继承的代码。
typedef struct A A;
typedef struct B B;

void processA(A *);
void processB(B *);

typedef union { void (*A)(A *); void (*B)(B *); } U;

U Ps[] = { {.A = processA}, {.B = processB} };

int main(void)
{
    Ps[0].A(0); // 0 used for example; normally you would supply a pointer to an A.
    Ps[1].B(0); // 0 used for example; normally you would supply a pointer to a B.
    return 0;
}
必须使用正确的成员名调用函数;此方法只允许在每个数组元素中存储一个或另一个指针,而不执行奇怪的函数别名


另一种选择是使用代理函数,当使用指向
char
的指针的参数进行调用时,代理函数具有所需的类型,并且使用适当的类型调用实际函数:

typedef struct A A;
typedef struct B B;

void processA(A *);
void processB(B *);

typedef void (*processor_t)();

void processAproxy(char *A) { processA(A); }
void processBproxy(char *B) { processB(B); }

processor_t Ps[] = { processAproxy, processBproxy };

int main(void)
{
    char *a = (char *) address of some A object;
    char *b = (char *) address of some B object;
    Ps[0](a);
    Ps[1](b);
    return 0;
}

我在上面使用了
char*
,因为您已经说明您正在使用它,但我通常更喜欢
void*

没有参数列表,它将编译如果这是纯CIf,那么它将允许我将
a*
传递给
processB
。毕竟,任何指针类型都可以转换为
void*
,因此它很容易让我违反类型安全。从技术上讲,它编译时只会抛出一个警告。我的问题是,是否有可能在不使用初始值的情况下消除警告?我想知道,省略号是否也能达到同样的效果?(使其在没有警告的情况下编译)刚刚尝试过,得到了
test1.c:4:29:error:isoc要求在“…”之前有一个命名参数
,这就回答了这个问题。我想我应该猜到:)谢谢。这种行为可能不是由C标准定义的
processA
是一个指向
a
的指针的函数。
processor\u t
指向的类型是没有参数列表的函数。将指向第一类函数的指针转换为指向第二类函数的指针是合法的。但是,如果第二种类型用于调用函数,并且使用了类型为
void*
的参数,则
void*
参数的类型与所需的
a*
参数的类型不同。正如C标准所定义的那样,它们不兼容,行为也没有定义。@Andrey:你说得对,我使用了错误的术语。但是,这一点是正确的:如果调用
processA
,这是一个使用指向
a
的指针的函数,使用指向具有未指定参数列表的函数的指针和指向
void
的参数,则不会定义该行为,有一个代码可以在数组Ps中进行迭代。@cvoque:如果说有代码可以在数组中进行迭代,则不会传递有关数组元素如何使用的任何信息。代码可能包含switch语句或其他分派。@cvoque:如何调用这些函数?大概你有一些想要传递的指针。那个指针是什么类型的?例如,您是否通过向每个函数传递从原始
a*
B*
转换而来的
void*
来调用每个函数(无论类型如何)?或者你是在给它们传递实际的
A*
B*
值吗?我的意思是,在我的例子中,有一个泛型代码遍历数组Ps的条目,而不知道每个函数的确切类型。它总是传递一个char*@cvoque:在C 2011(N1570)6.2.7中,定义了兼容类型。大多数情况下,它们必须是相同的
void*
char*
A*
不兼容。(它们不可能是这样的,因为某些C实现为
char
指针保留了比指向更大对象的指针更多的信息;不同类型的指针在机器中可能有不同的表示形式。)然后,我们必须考虑,当用另一种类型的表达式声明函数时,调用一种表达式是否调用函数是允许的。