执行此代码时,我在第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
应用于函数的行为。