C语言 为什么在声明指向函数的泛型指针时出错?



执行此代码时,我在第ptr = (void* (void*, void*))sumx;行得到[Error] cast specifies function type

我正在尝试声明一个通用指针ptr到一个名为sumx的函数

任何帮助将不胜感激。谢谢。

# include <stdio.h>
int sum(int a, int b) {
return a+b;
}
int* sumx(int *a, int *b) {
int *p;
*p = *a+*b;
return p;
}
int main() {
int (*p) (int, int);
void* (*ptr)(void*, void*);
p = sum;
ptr = (void* (void*, void*))sumx;

int s = (*p)(5, 6);
int a = 10;
int b = 20;
int *y = (*ptr)(&a, &b);
printf("%dn", s);
printf("%dn", *y);
return 0;
}

你在演员表中缺少一个(*),应该是这样的:

ptr = ( void* (*)(void*, void*) )sumx;

但是,当使用这样的函数指针时,使用typedef语句通常要清晰得多:

#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b)
{
return a + b;
}
int* sumx(int* a, int* b)
{
int* p = malloc(sizeof(int)); // Need to allocate some memory
*p = *a + *b;
return p;
}
typedef int (*ifncptr)(int, int);
typedef void* (*vpfncptr)(void*, void*);
int main()
{
ifncptr p;
vpfncptr ptr;
p = sum;
ptr = (vpfncptr)sumx;
int s = p(5, 6); // You can just use the fn-ptr for this call ...
int a = 10;
int b = 20;
int* y = ptr(&a, &b); // ^ ... and here, also!
printf("%dn", s);
printf("%dn", *y);
free(y); // Don't forget to free the memory.
return 0;
}
int* sumx(int *a, int *b) {
int *p;
*p = *a+*b;
return p;
}

您正在写入未初始化的指针,请使用malloc保留空间:

int *p = malloc(sizeof(*p));

并回答您的问题:

void* (*ptr)(void*, void*);

不是sumx的有效签名,而是:

int *(*ptr)(int *,  int*);

为什么在声明指向函数的泛型指针时出错?

因为在 C 语言中不存在指向函数的泛型指针这样的东西。void*是指向对象(变量(的通用指针。void*通常只能与对象指针一起使用,而不能与函数指针一起使用。

但是,可以在一个函数指针到另一个函数指针之间进行强制转换,但是在调用实际函数时,必须通过正确的函数指针类型执行此操作。


您还有其他各种关于不分配内存等的错误,这些错误可以通过其他答案来解决。但是,让我们忽略所有这些,以及函数指针的使用,在这种情况下,函数指针并不能真正满足目的。您实际想要做的事情可以通过现代标准 C 通过以下方式实现:

#include <stdio.h>
int sum_int(int a, int b) {
return a + b;
}
int sum_intp(const int *a, const int *b) {
return *a + *b;
}
#define sum(a,b) ( (void)_Generic((b), int:0, int*:0),/*NOTE: comma operator*/ 
_Generic((a),  
int:  sum_int, 
int*: sum_intp)(a,b) )
int main(void) 
{
int a=10;
int b=20;
printf("%dn", sum(a, b));
printf("%dn", sum(&a, &b));
//printf("%dn", sum(a, &b)); //compiler error
//printf("%dn", sum((float)a, b)); //compiler error
return 0;
}

C11_Generic宏在编译时确定类型。宏的伪代码为:

  • 检查参数 b 是否为有效类型。
  • 丢弃此参数 b 检查中的值 - 它只是在错误类型的情况下生成编译器错误。
  • 逗号运算符。
  • "检查参数 a 是否也有效,然后根据 a 的类型调用正确的函数。

这是类型安全的,无需void*或函数指针。

主要问题

您实际上不能在表达式中使用函数。在表达式中使用函数时,它会自动转换为指向该函数的指针。1

这意味着您的强制转换不应尝试转换为像void *(void *, void *)这样的函数类型,而应该转换为像void *(*)(void *, void *)这样的指向函数类型的指针类型。

两个问题

C 允许将指向函数的指针转换为不同类型的指向函数的指针,但是,当调用函数时,用于调用的指针应遵守有关与实际函数定义兼容性的某些规则。将参数或返回类型从int *更改为void *不遵守这些规则。因此,对于您拥有的类型,(*ptr)(&a, &b)不是一个合适的调用。

sumx中,p*p = *a + *b;之前没有初始化,所以不能期望它指向任何东西。您应该初始化它,可能使用p = malloc(sizeof *p);.调用malloc后,应测试结果。如果等于NULL,则程序应打印错误消息并退出或以其他方式处理分配内存的失败。

脚注

1有两个例外。一种是当你用&手动获取函数的地址时,没有自动转换。另一种是,当sizeof应用于函数时,没有转换,但随后存在约束冲突。C 标准没有定义将sizeof应用于函数的行为。

相关内容

  • 没有找到相关文章

最新更新