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]
是指向一个2int
s数组的指针。给出了详细的解释。第二个或第三个?你没有从零开始计数你读过我的链接吗?int(*)[2]
没有索引到数组中。它说数组的大小是2。