RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 623367
Accepted
MaximPro
MaximPro
Asked:2020-02-04 23:31:43 +0000 UTC2020-02-04 23:31:43 +0000 UTC 2020-02-04 23:31:43 +0000 UTC

使用指针调用函数的语法

  • 772

我的问题是,这样做的目的是什么?

有这个指针:int (*a)() = ownfucntion; /// ownfucntion - любая пользовательская функция.

我们可以这样调用这个函数:a();

我们可以这样做:(*a)();

逻辑在哪里?通常,解引用用于从指针获取值。这里的结果是一样的:如果你想取消引用,如果你不想取消引用,函数将作为结果被调用。

c
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. AnT stands with Russia
    2020-02-04T23:55:24Z2020-02-04T23:55:24Z

    在标准 C 中,函数调用通常总是精确地完成,并且只能通过函数指针完成,即 运算符()需要一个指针操作数。sizeof并且除,_Alignof和 unary之外的所有上下文中的类型“函数”都会&自动隐式转换为类型“指向函数的指针”(这种现象通常称为函数类型衰减)。

    因此,即使您编写ownfunction(),实际上也会发生隐式转换,(int (*)()) ownfunction并且运算符()已经应用于此转换的结果。

    尝试将一元运算符显式应用于*函数指针会导致该应用程序(“函数”类型)的结果立即自动“下降”回类型“指针”(上述上下文除外)。从这里开始,作为副作用,它遵循一元运算符对函数指针的可选/“无限”应用的可能性,以及在显式获取函数指针时*使用一元运算符的可选性。&

    (也就是说,为了说明这种运算符行为,*根本不需要显式a函数指针。函数本身的示例很好地说明了这一点。)

    PS 这种情况在很大程度上与数组的情况(数组类型衰减)是对称的,唯一的区别是数组被隐式转换为“指向元素的指针”类型而不是“指向整个数组的指针”,这防止了可能性一元运算符*对数组的“无限”应用。但总体思路是一样的。


    有趣的是,在 C 语言的史前版本中(参见《C 参考手册》),Dennis Ritchie()仅通过“函数”类型精确定义了运算符的行为,即 它的左边()应该是一个“函数”类型的表达式,而不是“指向函数的指针”。正是在这种情况下,没有从类型“函数”到类型“指向函数的指针”的隐式转换。后来的某个地方(在 K&R C 中?),运算符()突然开始需要一个“函数指针”类型的操作数。

    为什么会发生这样的转变?很难说。也许语言的作者被统一函数类型衰减和数组类型衰减的可能性所吸引。运算符包含在异常上下文列表中这一事实也隐含地表明了这一点sizeof,从而使表达式sizeof функция非法。看起来,为什么它被包含sizeof在例外列表中?可以允许函数类型衰减并悄悄sizeof地sizeof функция返回函数指针的大小。但不是。可能的原因是衰减行为与数组的统一。

    • 10
  2. Best Answer
    Vlad from Moscow
    2020-02-05T08:20:40Z2020-02-05T08:20:40Z

    除了一种情况外,函数指示符总是转换为函数指针。

    来自 C 标准(6.3.2.1 左值、数组和函数指示符)

    4 函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符 65) 或一元 & 运算符的操作数,否则类型为“函数返回类型”的函数指示符将转换为类型为“指向函数返回类型的指针”的表达式。

    虽然这个引用里面写的是operator的使用sizeof,但是实际上这个函数是不能在operator中使用的sizeof。

    C 标准(6.5.3.4 sizeof 和 alignof 运算符)

    1 sizeof 运算符不应应用于具有函数类型或不完整类型的表达式、此类类型的括号名称或指定位域成员的表达式

    因此,当使用后缀函数调用表达式时,函数名称被隐式转换为函数指针(6.5.2.2 函数调用)

    1 表示被调用函数的表达式 92) 应具有指向返回 void 或返回完整对象类型而不是数组类型的函数的类型指针。

    对此,你甚至可以写一个表达式,如下面的演示程序所示

    #include <stdio.h>
    
    void f( void )
    {
        puts( "Oh...At last I am called!" );
    }
    
    int main(void) 
    {
        ( **********f)();
    
        return 0;
    }
    

    程序输出到控制台:

    Oh...At last I am called!
    

    因为根据 C 标准(6.5.3.2 地址和间接运算符)

    4 一元运算符 * 表示间接。如果操作数指向一个函数,则结果是一个函数指示符;如果它指向一个对象,则结果是指定该对象的左值。如果操作数的类型为“指向类型的指针”,则结果的类型为“类型”。如果为指针分配了无效值,则一元 * 运算符的行为未定义。 102

    也就是说,首先将函数符号隐式转换为函数指针。然后,在应用运算符之后,*该指针将转换为函数符号,并立即转换回函数指针,依此类推。

    在特定编译器允许的情况下,您可以将尽可能多*的运算符应用于函数符号。


    总结起来,我们可以说以下几点。为了声明函数,引入了它们的标识符,以便它可以用来引用函数并将一个函数与另一个函数区分开来。在这种情况下,函数本身可能尚未定义,而只是声明。

    当这个函数标识符,或者换句话说,函数指示符,在表达式中使用时,它被转换为函数指针的类型。

    表达式使用值。应该为表达式中使用的函数符号分配什么值?

    使用函数的地址作为值自然是合理的,因为所有的函数都是为了执行而创建的。并且您只能通过将控制传递到定义此函数的地址来执行函数。

    因此,它的地址被作为函数的值,即表达式中的函数被转换为指向自身的指针。

    将函数隐式转换为函数指针的唯一例外是 & 运算符的使用。无需将函数隐式转换为指向它的指针,因为使用 & 运算符因此是显式获取函数的地址。

    • 5
  3. Harry
    2020-02-04T23:37:21Z2020-02-04T23:37:21Z

    执行隐式转换。函数的名称及其地址是完全可以互换的,因此,需要将&(和*)应用于函数的名称和地址。

    例如,两个选项都有效:

    int (*a)() = ownfucntion;
    int (*a)() = &ownfucntion;
    

    好吧,你甚至可以这样打电话:)

    (********************&********************a)();
    
    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5