C/C++中函数值的含义是什么?

6
如果我们有一个函数指针,那么解引用该指针会发生什么?请参考如何对函数指针进行解引用?
void f() {
    printf("called");
}

接下来的代码将输出"calledcalled":
```python print("called" * 2) ```
f();
(*f)();

我不太理解这是怎么工作的... *ff 有什么区别?为什么会使用后一种语法来调用函数呢?

1
这需要两个问题,一个关于C,一个关于C ++,因为它们有微妙的不同规则(尽管最终行为相同)。 - Ben Voigt
3个回答

6

在C++中,有两种调用函数的方式:

1. 按照函数名称:

f();

通过函数指针:

typedef void (*fptr_t)();
fptr_t fptr = &f;
(*fptr)();

现在,对函数名使用取地址运算符(&f)显然会创建一个函数指针。但是当满足某些条件时,函数名可以隐式转换为函数指针。因此,上述代码可以写成:

typedef void (*fptr_t)();
fptr_t fptr = f; // no address-of operator, implicit conversion
(*fptr)();

您的第二个示例就是这样做的,但是使用临时变量来保存函数指针,而不是使用命名本地变量。

在创建函数指针时,我更喜欢使用地址符号,因为意义更加清晰。

相关说明:如果提供了函数指针,则函数调用运算符将自动对其进行解引用。 因此,下面的代码也是合法的:

typedef void (*fptr_t)();
fptr_t fptr = &f;
fptr();

对于模板而言,这是非常有用的,因为相同的语法适用于传递函数指针或实现operator()的函数对象(仿函数)。

而对于成员指针,这两个快捷方法都不起作用,你需要使用显式的取地址和解引用运算符。


在C语言中,@Mehrdad解释道,所有的函数调用都使用函数指针。


我预计在C++0x中,我们将看到更多微妙的问题,包括lambda等等... - user541686

6
第一种写法在某种程度上是第二种写法的语法糖。第二种写法明确表明你是通过指针进行调用的,主要用于函数指针而不是常规函数,以使区别更加明显。

2
@Matti:不,第二个是对指针进行解引用并调用函数,这正是第一个隐式执行的操作。(*符号有几种含义--它既可以是解引用运算符,也可以是指针声明,除了乘法。不要混淆它们。) - user541686
@Jan:我认为第一个隐式地被解释成这样,而不是第二个... f 是函数指针,而不是其地址的值。 - user541686
@Mehrdad:我非常确定直接调用函数和通过函数指针调用函数(至少在没有优化的情况下)编译方式不同,因此默认情况下 f 只是函数 f 而不是指向它的指针。我所说的“隐式获取指针”是指缺少 & 符号。 - Matti Virkkunen
2
大家好,f*f是一样的,因为当应用于函数时,间接操作符返回一个函数指示器,它与函数本身相同。这在这里有详细讨论。 - Frédéric Hamidi
@Ben:f 是 (r-value) 指针,我不明白这有什么不同。 - user541686
显示剩余13条评论

2

就像数组类型几乎完全等同于相应的指向元素类型的指针类型一样,函数类型完全等同于相应的指向函数类型的指针类型:

void (*func1)() = f;  // function type -> pointer-to-function type
void (*func2)() = &f; // pointer-to-function type -> pointer-to-function type

并且也
void (*func)() = ...;
func();               // pointer-to-function type + function-call operator
(*func)();            // function type + function-call operator

So, in

(*f)();

你正在对 f 进行解引用操作(隐式转换为 &f),然后应用函数调用运算符。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接