【问题标题】:Are parameters copied twice for inline in c?c语言中的内联参数是否复制了两次?
【发布时间】:2017-05-24 11:33:18
【问题描述】:

我有一个关于 c/c++ 中的内联函数和参数复制的问题。假设我想在没有内联说明符的情况下运行这个函数:

void my_func(int param)
{
    my_inner_func(param);
}

参数将首先复制到my_func,然后再复制到my_inner_func。如果函数my_funcinline,编译器是否会为my_inner_func 参数只复制一次param,或者无论如何复制两次。 我将不胜感激。

编辑:如果 c 和 c++ 不同,我想请教他们的解释。

【问题讨论】:

  • 我编辑了问题
  • inline 关键字和函数内联很久以前就变得不相关了。请参阅here 了解更多信息。
  • @Quentin 他们密切相关。只是不严格相互依赖。

标签: c++ c function inline


【解决方案1】:

C 和 C++ 都根据抽象机器指定程序的行为。

my_funcint param存在于这个抽象机中,与my_inner_funcint param不同。他们有不同的身份。如果你取其中一个的地址和另一个的地址,它们肯定会比较不相等。

但是,如果您不获取其中任何一个的地址,则两者都不需要地址。

如果您对int 所做的只是分配或初始化它,那么使用它来分配或初始化另一个int,编译器可以证明没有定义的方法可以通过间接方式到达中间int(像一个指针),那么中间的int 不需要存在于实际的目标机器上。

一些编译器在链接时会遇到问题。其他人没有。

某些操作会阻止 int 的存在被忽略。其他人不会。

我在您的示例中看不到任何需要中间 int 存在于目标计算机上的内容。

【讨论】:

    【解决方案2】:

    只要遵循as if 规则,编译器就可以为所欲为。

    规则规定,在任何时候你尝试测量程序的状态,它都会给出正确的答案。

    在您不测量它的地方,它可以重新排序操作。

    当编译器进行优化时,它将能够删除内联和非内联代码的第二个参数副本,除非有代码试图发现这一点。然后它必须生成满足 as-if 规则的代码,并可能增加副本的数量。

    【讨论】:

      【解决方案3】:

      inline 它只是对编译器的“建议”,可以或不能inline 你的函数。显然也可以选择inline一个你没有显式声明inline的函数。

      换句话说,根据您的编译器和优化设置,您应该查看生成的汇编程序以获得答案。

      【讨论】:

      • 看起来我记得明确的“inline 被忽略”有什么严重错误......我的错。公平地说,这是一个相当模糊的主题,因为它涉及标准措辞和实施细节。
      • 我认为 "suggestion" 不能很好地描述 inline 所做的事情。它通过允许在多个翻译单元中定义来放宽 ODR,实际上在使用该功能的所有翻译单元中添加了新的定义要求。这一新要求具有有意的副作用,即允许跨翻译单元进行内联扩展。另一方面,如果使用 LTO,这不是一个严格的要求。这是一个内联的建议,就像授予驾驶执照是一个驾驶汽车的建议一样(不好的类比,不适用于所有级别)。
      • @user2079303 ..bad 作为我最糟糕的英语... ;)
      【解决方案4】:

      这取决于。内联函数(顺便说一句,最好让编译器决定是否这样做)必须公开与正常而非内联版本相同的可观察行为。所以最简单的方法是将参数复制两次。 如果内部函数没有写入第二个副本,编译器可能足够聪明。

      【讨论】:

      • 我认为 OP 被截断了伪代码;当然,您所描述的将是另一种可以优化的极端情况。
      • 好吧,如果你不能假设 OP 在通话后没有从param 读取数据,我认为你不能假设 OP 在任何时候都没有获取任何一个参数的地址,这是进行优化的另一个要求。
      【解决方案5】:

      如果函数没有内联,在大多数架构上,函数调用本身的成本将大大高于复制int

      在参数通过寄存器传递的系统上,用于传递单个int 参数的寄存器在进入第一个函数时已经保存了该值,它可以将其传递给下一个函数而无需创建新副本。

      不要为小事出汗!

      【讨论】:

        【解决方案6】:

        好吧,在内联函数中,编译器可以访问所有涉及的代码内联,所以它可以检测你是否真的在修改参数,所以如果你的函数没有,它可以避免复制修改参数。说了这么多,你面临的问题是什么?

        【讨论】:

        • 没有问题,只是好奇。
        • @Bremen,在这种情况下,恐怕这不是要问的正确论坛。
        猜你喜欢
        • 2019-06-01
        • 1970-01-01
        • 2016-03-04
        • 1970-01-01
        • 2015-10-08
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        相关资源
        最近更新 更多