C++ 为什么将函数名用作函数指针等同于将运算符地址应用于函数名?

C++ 为什么将函数名用作函数指针等同于将运算符地址应用于函数名?,c++,syntax,function-pointers,C++,Syntax,Function Pointers,有趣的是,将函数名用作函数指针相当于将运算符地址应用于函数名 下面是一个例子 typedef bool (*FunType)(int); bool f(int); int main() { FunType a = f; FunType b = &a; // Sure, here's an error. FunType c = &f; // This is not an error, though. // It's equivale

有趣的是,将函数名用作函数指针相当于将运算符地址应用于函数名

下面是一个例子

typedef bool (*FunType)(int);
bool f(int);
int main() {
  FunType a = f;
  FunType b = &a; // Sure, here's an error.
  FunType c = &f; // This is not an error, though. 
                  // It's equivalent to the statement without "&".
                  // So we have c equals a.
  return 0;
}
使用名称是我们在数组中已经知道的。但你不能写这样的东西

int a[2];
int * b = &a; // Error!
它似乎与语言的其他部分不一致。这种设计的基本原理是什么

但是我很感兴趣的是为什么语言是这样设计的

更有趣的是,函数类型在用作参数时可以隐式转换为指向自身的指针,但在用作返回类型时不会转换为指向自身的指针

示例:

typedef bool FunctionType(int);
void g(FunctionType); // Implicitly converted to void g(FunctionType *).
FunctionType h(); // Error!
FunctionType * j(); // Return a function pointer to a function 
                    // that has the type of bool(int).

这是从C语言继承的一个特性

在C语言中,这是允许的,主要是因为函数名本身没有太多其他含义。使用实际函数所能做的就是调用它。如果你不打电话,你唯一能做的就是记下地址。由于没有歧义,任何时候函数名后面没有
表示对函数的调用,该名称的计算结果就是函数的地址

这实际上有点类似于语言的另一部分——数组的名称计算为数组第一个元素的地址,但在某些相当有限的情况下除外(用作
&
的操作数)


<>既然C允许,C++也一样,主要是因为同样的情况是正确的:你可以用函数来做的唯一的事情就是调用它或者取它的地址,所以如果名字没有后面跟着一个<代码>(
表示函数调用,然后名称计算为地址,没有歧义。

由于您专门询问此行为的基本原理,下面是我能找到的最接近的东西(从ANSI C90基本原理文档-):

3.3.2.2函数调用

指向函数的指针可以用作
(*pf)(
)或
pf()
。 后一种构造(未在基础文档中批准)出现在 C的一些现有版本,是明确的,不会使旧代码失效, 并且可以是一个重要的速记。速记对于 仅显示一个外部名称的包,该名称指定 包含指向对象和函数的指针的结构:成员 函数可以称为
图形。打开(文件)
而不是
(*graphics.open)(文件)
。函数指示符的处理可以 引出一些奇怪但有效的句法形式 声明:

int f ( ) , ( *pf ) ( ) ; 
那么以下所有表达式都是有效的函数调用:

( &f)(); f(); (*f)(); (**f)(); (***f)();
pf(); (*pf)(); (**pf)(); (***pf)();
前一节讨论了每行上的第一个表达式 第二个是常规用法。所有后续的 表达式利用函数的隐式转换 几乎在所有表达式上下文中,指针值的指示符。 委员会认为允许这些形式没有真正的危害;取缔 像
(*f)(
)这样的表单,同时仍然允许
*a
(对于
inta[])
, 只是看起来麻烦太多了


基本上,增加了函数指示符和函数指针之间的等价性,使函数指针的使用更加方便。

对于数组,使用运算符地址时,指针不会衰减:

int a[2];
int * p1 = a;      // No address-of operator, so type is int*
int (*p2)[2] = &a; // Address-of operator used, so type is int (*)[2]
这是有意义的,因为数组和指针是不同的类型,例如可以返回对数组的引用或在函数中传递对数组的引用

但是,对于函数,还有什么其他类型的函数呢

void foo(){}
&foo; // #1
foo;  // #2

假设只有#2给出了类型
void(*)()
,什么类型的
&foo
?没有其他可能性。

对函数唯一能做的就是调用它或获取它的地址
——你也可以用它初始化对函数的引用。@Cubbi:C没有引用,这个答案的全部要点是行为是从C继承的.从技术上讲,在C语言中,函数名的计算结果是函数的地址,即使在函数调用表达式中使用函数名也是如此;“表示被调用函数的表达式”必须具有指向函数类型的指针,为了适应这种情况,裸函数名的计算结果是指向函数的指针“除非它是
sizeof
或一元
&
的操作数”(分别为C99§§6.5.2.2p1和6.3.2.1p4)。我想这是因为函数指示符实际上是人类使用的语法糖。函数名实际上只是内存地址上的标签。环境实际上看不到单独的函数和指向它们的指针,它只看到指向地址的指令分支。这与环境将使用d的对象不同不同的寻址模式(直接或间接)你能解释一下类型
(*)[2]
。我不知道我是否能正确地想象它,但它像数组(指针)p2的第三个值吗?它的值也是地址吗?如
(*)[2]=&
。纠正我对指针值的看法
(*)[2]
,但基本上是这样,不是吗?@strosdman:
int(*)[2]
是指向一个2
int
s数组的指针。给出了详细的解释。第二个或第三个?你没有从零开始计数你读过我的链接吗?
int(*)[2]
没有索引到数组中。它说数组的大小是2。