为啥这两个函数指针在 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++ 中都是合法的?的主要内容,如果未能解决你的问题,请参考以下文章