为什么这些函数指针在C / C ++中都是合法的?

时间:2013-10-27 11:20:50

标签: c++ c pointers return function-pointers

我有这两个测试功能:

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

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

那为什么要这样做?

4 个答案:

答案 0 :(得分:7)

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

可以获得此类功能的地址:

int someFunc(int);

使用:

int (* someFuncPtr)(int) = someFunc;

或:

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

使用这样的指针也有语法糖,要么调用指向函数:

(*someFuncPtr)(5);

或使用简化语法:

someFuncPtr(5);

答案 1 :(得分:6)

由于C和C ++中的规则将函数转换为指向函数的指针,因此

(*fun)(m,n)fun(m,n)相同。

在C 2011中,规则是条款6.3.2.1 4:“函数指示符是具有函数类型的表达式。除非是 sizeof 运算符, _Alignof运算符或一元& 运算符的操作数,否则函数指示符的类型为“function”返回 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)

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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