这些在 C 中获取函数指针的方法有区别吗?
Is there a difference between these ways to get function pointers in C?
我在弄乱函数指针,发现以下程序有问题:
#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)));
时它也有效(我在看到上面的内容后假设)。
我想知道这是为什么,这两个选项之间是否有任何区别。这是未定义的行为吗,我只是很幸运,编译器是否认为所有这些都是我的意思,还是这里发生了一些我不明白的奇怪事情?
来自 ANSI/ISO 9899-1990 C 标准,第 6.2.2.1 节:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type."
这意味着 add
本身被转换为指针。 &add
也是一个指针,有点像定义;我认为这就是为什么它被明确排除在上面的段落之外。 *add
经过双重转换,将函数取消引用为指针,然后再次将其重新解释为指针。
我预计编译后的代码不会有任何差异。
实际上,函数名只是内存地址的标签,这使得它们成为地址持有者,就像指针一样。因此,您可以将函数名称视为某种方式的指针。因此,您可以使用与指针相同的引用运算符也就不足为奇了。
我在弄乱函数指针,发现以下程序有问题:
#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)));
时它也有效(我在看到上面的内容后假设)。
我想知道这是为什么,这两个选项之间是否有任何区别。这是未定义的行为吗,我只是很幸运,编译器是否认为所有这些都是我的意思,还是这里发生了一些我不明白的奇怪事情?
来自 ANSI/ISO 9899-1990 C 标准,第 6.2.2.1 节:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type."
这意味着 add
本身被转换为指针。 &add
也是一个指针,有点像定义;我认为这就是为什么它被明确排除在上面的段落之外。 *add
经过双重转换,将函数取消引用为指针,然后再次将其重新解释为指针。
我预计编译后的代码不会有任何差异。
实际上,函数名只是内存地址的标签,这使得它们成为地址持有者,就像指针一样。因此,您可以将函数名称视为某种方式的指针。因此,您可以使用与指针相同的引用运算符也就不足为奇了。