我正在搞乱函数指针,我注意到了以下程序:
#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)));
(我在看到上述内容后假设)之后,它也有效。
我想知道为什么会这样,如果这两个选项之间有任何区别。这是不确定的行为而且我很幸运,编译器是否认为通过所有这些我的意思是相同的,或者是否有一些奇怪的事情发生在这里我不明白?
答案 0 :(得分:4)
根据ANSI / ISO 9899-1990 C标准,第6.2.2.1节:
函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符或一元&amp; 运算符的操作数,否则将转换类型为“函数返回类型”的函数指示符到具有类型“指向函数返回类型的指针”的表达式。
这意味着add
本身会转换为指针。 &add
也是一个指针,根据定义;我认为这就是为什么它被明确排除在上面的段落之外。 *add
进行双重转换,将函数解除引用作为指针,然后再将其重新解释为指针。
我不认为编译代码会有任何不同。
答案 1 :(得分:0)
实际上,函数名只是内存地址的标签,这使得它们像指针一样使用地址持有者。因此,您可以将函数名称视为指针。因此,您可以使用与指针相同的引用运算符,这不足为奇。