为什么在声明一个函数的通用指针时出现错误?

问题描述 投票:0回答:1

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

我正试图声明一个通用指针 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("%d\n", s);
    printf("%d\n", *y);
    return 0;
}
c function pointers function-pointers
1个回答
3
投票

你缺少一个 (*) 中,应该是这个。

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("%d\n", s);
    printf("%d\n", *y);
    free(y); // Don't forget to free the memory.
    return 0;
}

2
投票
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*);

1
投票

为什么在声明一个函数的通用指针时出现错误?

因为在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("%d\n", sum(a, b));
  printf("%d\n", sum(&a, &b));
  //printf("%d\n", sum(a, &b)); //compiler error
  //printf("%d\n", sum((float)a, b)); //compiler error
  return 0;
}

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

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

这是类型安全的,并且消除了对 void* 或函数指针。


1
投票

主要问题

实际上你不能在表达式中使用函数。当在表达式中使用函数时,它会自动转换为函数的指针。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 到一个函数。

© www.soinside.com 2019 - 2024. All rights reserved.