我的问题是,这样做的目的是什么?
有这个指针:int (*a)() = ownfucntion; /// ownfucntion - любая пользовательская функция.
我们可以这样调用这个函数:a();
我们可以这样做:(*a)();
逻辑在哪里?通常,解引用用于从指针获取值。这里的结果是一样的:如果你想取消引用,如果你不想取消引用,函数将作为结果被调用。
我的问题是,这样做的目的是什么?
有这个指针:int (*a)() = ownfucntion; /// ownfucntion - любая пользовательская функция.
我们可以这样调用这个函数:a();
我们可以这样做:(*a)();
逻辑在哪里?通常,解引用用于从指针获取值。这里的结果是一样的:如果你想取消引用,如果你不想取消引用,函数将作为结果被调用。
在标准 C 中,函数调用通常总是精确地完成,并且只能通过函数指针完成,即 运算符
()需要一个指针操作数。sizeof并且除,_Alignof和 unary之外的所有上下文中的类型“函数”都会&自动隐式转换为类型“指向函数的指针”(这种现象通常称为函数类型衰减)。因此,即使您编写
ownfunction(),实际上也会发生隐式转换,(int (*)()) ownfunction并且运算符()已经应用于此转换的结果。尝试将一元运算符显式应用于
*函数指针会导致该应用程序(“函数”类型)的结果立即自动“下降”回类型“指针”(上述上下文除外)。从这里开始,作为副作用,它遵循一元运算符对函数指针的可选/“无限”应用的可能性,以及在显式获取函数指针时*使用一元运算符的可选性。&(也就是说,为了说明这种运算符行为,
*根本不需要显式a函数指针。函数本身的示例很好地说明了这一点。)PS 这种情况在很大程度上与数组的情况(数组类型衰减)是对称的,唯一的区别是数组被隐式转换为“指向元素的指针”类型而不是“指向整个数组的指针”,这防止了可能性一元运算符
*对数组的“无限”应用。但总体思路是一样的。有趣的是,在 C 语言的史前版本中(参见《C 参考手册》),Dennis Ritchie
()仅通过“函数”类型精确定义了运算符的行为,即 它的左边()应该是一个“函数”类型的表达式,而不是“指向函数的指针”。正是在这种情况下,没有从类型“函数”到类型“指向函数的指针”的隐式转换。后来的某个地方(在 K&R C 中?),运算符()突然开始需要一个“函数指针”类型的操作数。为什么会发生这样的转变?很难说。也许语言的作者被统一函数类型衰减和数组类型衰减的可能性所吸引。运算符包含在异常上下文列表中这一事实也隐含地表明了这一点
sizeof,从而使表达式sizeof функция非法。看起来,为什么它被包含sizeof在例外列表中?可以允许函数类型衰减并悄悄sizeof地sizeof функция返回函数指针的大小。但不是。可能的原因是衰减行为与数组的统一。除了一种情况外,函数指示符总是转换为函数指针。
来自 C 标准(6.3.2.1 左值、数组和函数指示符)
虽然这个引用里面写的是operator的使用
sizeof,但是实际上这个函数是不能在operator中使用的sizeof。C 标准(6.5.3.4 sizeof 和 alignof 运算符)
因此,当使用后缀函数调用表达式时,函数名称被隐式转换为函数指针(6.5.2.2 函数调用)
对此,你甚至可以写一个表达式,如下面的演示程序所示
程序输出到控制台:
因为根据 C 标准(6.5.3.2 地址和间接运算符)
也就是说,首先将函数符号隐式转换为函数指针。然后,在应用运算符之后,
*该指针将转换为函数符号,并立即转换回函数指针,依此类推。在特定编译器允许的情况下,您可以将尽可能多
*的运算符应用于函数符号。总结起来,我们可以说以下几点。为了声明函数,引入了它们的标识符,以便它可以用来引用函数并将一个函数与另一个函数区分开来。在这种情况下,函数本身可能尚未定义,而只是声明。
当这个函数标识符,或者换句话说,函数指示符,在表达式中使用时,它被转换为函数指针的类型。
表达式使用值。应该为表达式中使用的函数符号分配什么值?
使用函数的地址作为值自然是合理的,因为所有的函数都是为了执行而创建的。并且您只能通过将控制传递到定义此函数的地址来执行函数。
因此,它的地址被作为函数的值,即表达式中的函数被转换为指向自身的指针。
将函数隐式转换为函数指针的唯一例外是 & 运算符的使用。无需将函数隐式转换为指向它的指针,因为使用 & 运算符因此是显式获取函数的地址。
执行隐式转换。函数的名称及其地址是完全可以互换的,因此,需要将
&(和*)应用于函数的名称和地址。例如,两个选项都有效:
好吧,你甚至可以这样打电话:)