为啥这两个函数指针在 C/C++ 中都是合法的?

Posted

技术标签:

【中文标题】为啥这两个函数指针在 C/C++ 中都是合法的?【英文标题】:Why are both these function pointers legal in C/C++?为什么这两个函数指针在 C/C++ 中都是合法的? 【发布时间】:2013-11-06 04:51:40 【问题描述】:

我有这两个测试功能:

int apply_a(int (*fun)(int, int), int m, int n) 
    return (*fun)(m,n);


int apply_b(int (*fun)(int, int), int m, int n) 
    return fun(m,n);

它们似乎返回不同的东西,那么为什么它们都产生相同的结果?

int add(int a, int b) return a + b;

int res_a = apply_a(add, 2, 3); // returns 5
int res_b = apply_b(add, 2, 3); // returns 5

我会假设其中一个会返回指针地址或指针本身;而不是存储在指针上的值...

那么为什么要这样做呢?

【问题讨论】:

因为任何一种语法(带或不带星号)对于通过指针调用函数都是有效的。第二种情况是调用(你可以通过括号和传递的参数来判断)。 两者都不好。你应该使用(***fun)(m, n) 来获得三星级程序员的资格。 【参考方案1】:

因为在处理非成员函数的地址和使用指向它们的指针时,C++ 提供了语法糖。

可以得到该函数的地址:

int someFunc(int);

与任一:

int (* someFuncPtr)(int) = someFunc;

或:

int (* someFuncPtr)(int) = &someFunc;

也有使用这种指针的语法糖,或者调用指向函数:

(*someFuncPtr)(5);

或使用简化语法:

someFuncPtr(5);

【讨论】:

请记住,这同样适用于静态类方法(至少在我检查过的 Visual C++ 2012 上)) 这也适用于 C 语言吗?还是仅适用于 C++ 的糖规则? C++ 为“函数”类型引入了另一种表示法:int(int),它可以转换为int(*)(int)someFunc 的类型为 int(int),而 &someFunc 的类型为 int(*)(int) @ElectricCoffee,它也适用于 C。【参考方案2】:

(*fun)(m,n)fun(m,n) 相同,这是因为 C 和 C++ 中的规则将函数转换为指向函数的指针。

在 C 2011 中,规则是第 6.3.2.1 4 条:“函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符、_Alignof 运算符 或一元 & 运算符的操作数,否则为“函数返回”类型的函数指示符type”被转换为具有“指向返回type的函数的指针”类型的表达式。在 C++ 中,规则是第 4.3 条。

请注意,函数指示符不仅仅是命名函数的标识符。它可以是一个标识符,也可以是另一个表达式。比如foo是一个函数的名字,上面会自动转换成指向函数的指针。那么,由于foo 是指向函数的指针,所以*foo 就是函数。这意味着你可以写:

(*fun)(m,n)

结果是fun 自动转换为指针,然后* 计算为函数,然后*fun 转换回指针,然后调用函数。你可以继续写:

(**************fun)(m,n)

这与fun(m,n) 相同。每个* 都会再次生成函数,但编译器会自动将其转换回指针。您可以永远继续这场战斗,但编译器将永远获胜。

其实这些都是一样的效果:

(&fun)(m,n)
( fun)(m,n)
(*fun)(m,n)

【讨论】:

【参考方案3】:

这是因为您没有返回这些值的内存地址。 用指针调用函数不会改变它的值,它仍然在调用函数。您可以做的是将一个值返回给一个变量,然后获取它的内存地址,例如:

int result = fun(m,n);
cout << "the result " << result << " pointing at " << &result << endl;

【讨论】:

【参考方案4】:

在 C 和 C++ 中,函数的名称也是指向函数代码的指针。作为任何指针,您可以使用* 取消引用它们,这在函数指针的情况下意味着调用函数,除了取消引用之外,您还可以在它们之后使用括号,就像在您的apply_a 案例中一样。但对 C 和 C++ 函数的有效调用也只是通过它们的名称来调用它们,即 apply_b 大小写。

【讨论】:

这不是名字。 任何函数表达式,而不仅仅是函数名,都将被转换为指向函数的指针。

以上是关于为啥这两个函数指针在 C/C++ 中都是合法的?的主要内容,如果未能解决你的问题,请参考以下文章

函数返回多个值(c/c++)

(C/C++函数返回多个值)

函数指针

C语言中free掉一段空间后为啥还要使用NULL

回调函数(callback)是啥? ,,

C 语言字符串拷贝 ( 指针使用前判空 | while 空语句 )