在C中获取函数指针的这些方法之间有区别吗?

时间:2015-04-14 03:58:33

标签: c function function-pointers

我正在搞乱函数指针,我注意到了以下程序:

#include <stdio.h>

int operation (int x, int y, int (*fptr)(int, int))
{
        int z;
        z = (*fptr)(x, y);
        return (z);
}
int add(int a, int b) {
        return a+b;
}
int main(int argc, char** argv) {
        /* This line */ printf("%d\n", operation(1, 2, add));
}

运行此程序会产生3,因为它应该。

但是,在标记为/* This line */的行上,我注意到如果该行已更改为其他两个选项中的任何一个,则还会导致3: printf("%d\n", operation(1, 2, *add)printf("%d\n", operation(1, 2, &add)(注意添加的星号和&符号)。

当我尝试printf("%d\n", operation(1, 2, *(&add)));printf("%d\n", operation(1, 2, &(*add)));(我在看到上述内容后假设)之后,它也有效。

我想知道为什么会这样,如果这两个选项之间有任何区别。这是不确定的行为而且我很幸运,编译器是否认为通过所有这些我的意思是相同的,或者是否有一些奇怪的事情发生在这里我不明白?

2 个答案:

答案 0 :(得分:4)

根据ANSI / ISO 9899-1990 C标准,第6.2.2.1节:

  

函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符或一元&amp; 运算符的操作数,否则将转换类型为“函数返回类型”的函数指示符到具有类型“指向函数返回类型的指针”的表达式。

这意味着add本身会转换为指针。 &add也是一个指针,根据定义;我认为这就是为什么它被明确排除在上面的段落之外。 *add进行双重转换,将函数解除引用作为指针,然后再将其重新解释为指针。

我不认为编译代码会有任何不同。

答案 1 :(得分:0)

实际上,函数名只是内存地址的标签,这使得它们像指针一样使用地址持有者。因此,您可以将函数名称视为指针。因此,您可以使用与指针相同的引用运算符,这不足为奇。