c - 为什么这个指向函数的指针可以在没有警告或错误的情况下工作?

标签 c function-pointers

知道这个调用:

pow(4);

将生成此错误消息:

 error: too few arguments to function ‘pow’

我正在学习指向函数的指针,当看到下面这段代码工作时我感到很惊讶。但是为什么?

#include<stdio.h>
#include<math.h>

void aux(double (*function)(), double n, double x);

int main(void)
{
    aux(pow, 4, 2); 

    aux(sqrt, 4, 0);

    return 0;
}

void aux(double (*function)(double), double n, double x)
{   
    if(x == 0)
        printf("\nsqrt(%.2f, %.2f): %f\n", n, x, (*function)(n));  
    else
        printf("\npow(%.2f, %.2f): %f\n", n, x, (*function)(n));  
}

我编译使用:

gcc -Wall -Wextra -pedantic -Wconversion -o test test.c -lm

结果是:

pow(4.00, 2.00): 16.000000

sqrt(4.00, 0.00): 2.000000

如果我把第一次调用aux的第三个参数改成3,结果就变成了:

pow(4.00, 3.00): 64.000000

sqrt(4.00, 0.00): 2.000000

还有一个问题。在这种情况下,声明和使用函数指针的正确方法是什么?

最佳答案

这个:

void aux(double (*function)(), double n, double x);

函数 使用旧式非原型(prototype)声明。空括号 () 表示该函数采用固定但未指定数量和类型的参数。

C 仍然允许这种向后兼容的声明。原型(prototype)(指定参数类型的函数声明)于 1989 年由 ANSI C 引入。在此之前,无法在函数声明中指定参数类型,并且编译器无法检查调用是否传递了正确的数字和参数类型。

这样的声明是“过时的”,这意味着可以从 future 的 C 标准中删除对它们的支持(但在 20 多年的时间里,委员会一直没有考虑删除它们)。使用错误数量的参数类型调用函数不一定会被编译器诊断出来,并且行为是未定义的。

当一个函数类型有原型(prototype)而另一个没有时,函数类型的兼容性规则有点复杂。这些类型:

double(double)         /* function with one double parameter
                          returning double */
double(double, double) /* function with two double parameters
                          returning double */

彼此不兼容,但它们与此类型兼容:

double()   /* function with a fixed but unspecified number of parameters
              returning double */

这使得在没有来自编译器的诊断的情况下进行错误调用成为可能。

为避免此问题,始终使用原型(prototype):

void aux(double (*function)(double, double), double n, double x);

您不仅可以从编译器获得更好的诊断,而且不必担心非原型(prototype)函数的复杂兼容性规则(如果您好奇的话,在 N1570 6.7.6.3 段落中指定) 16).

关于c - 为什么这个指向函数的指针可以在没有警告或错误的情况下工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28282577/

相关文章:

c - 使用 fputc 和 fgetc 写入文件最终只有 0

c - 为什么我不能将函数指针强制转换为 (void *)?

rust - 我如何从 Rust 调用原始地址?

c++ - 唯一标识指向成员函数的指针的方法?

c - 用C写shell,如何区分交互模式和批处理模式

比较 char* 和 char

c - scanf() 将换行符留在缓冲区中

c++ - 使用 void 指针时转换函数(CUBA Nint 例程)

c - 在函数内部时,如何获取它的返回地址?

c - 作为 C 结构成员的函数指针数组