c中的内联参数是否复制了两次?
Are parameters copied twice for inline in c?
我对 c/c++ 中的内联函数和参数复制有疑问。假设我想 运行 这个函数没有内联说明符:
void my_func(int param)
{
my_inner_func(param);
}
param 将首先复制到 my_func
,然后再复制到 my_inner_func
。如果函数 my_func
是 inline
,编译器会只为 my_inner_func
参数复制一次 param
还是两次。
我将不胜感激。
编辑:如果 c 和 c++ 有所不同,我想寻求解释。
C 和 C++ 都根据抽象机指定程序的行为。
my_func
的int param
存在于这个抽象机中,与my_inner_func
的int param
不同。他们有不同的身份。如果你取其中一个的地址和另一个的地址,它们保证比较不相等。
但是,如果您不获取其中任何一个的地址,则两者都不需要地址。
如果你对一个 int
所做的只是赋值或初始化它,然后用它来赋值或初始化另一个 int
,编译器可以证明没有定义的方式到达中间int
通过间接寻址(如指针),那么中间 int
不需要存在于实际目标机器上。
一些编译器在 link 时执行此操作时会遇到问题。其他人没有。
一些操作会阻止 int
的存在被删除。其他人不会。
我在您的示例中看不到任何需要中间 int
存在于目标机器上的内容。
inline
它只是编译器的一个 "suggestion",可以或不能 inline
你的函数。显然也可以选择 inline
一个你没有显式声明的函数 inline
.
换句话说,根据您的编译器和优化设置,您应该查看生成的汇编程序以获得答案。
只要遵循as if
规则,编译器就可以为所欲为。
规则规定,在任何时候你尝试测量程序的状态,它都会给出正确的答案。
在你不测量它的地方,它可以重新排序操作。
当编译器进行优化时,它将能够删除内联和非内联代码的第二个参数副本,除非有代码试图发现这一点。然后它必须生成符合假设规则的代码,并可能增加副本数。
视情况而定。内联函数(顺便说一句,最好让编译器决定是否执行此操作)必须公开与正常而非内联版本相同的可观察行为。所以最简单的方法是复制参数两次。编译器可能足够聪明,可以优化第二个副本如果内部函数不写入它。
如果函数不是内联的,在大多数体系结构上,函数调用本身的成本将明显高于复制 int
。
在寄存器中传递参数的系统上,用于传递单个 int
参数的寄存器在进入第一个函数时已经保存了值,它可以将它传递给下一个函数而无需创建新的复制.
不要为小事操心!
嗯,在内联函数中,编译器可以访问所有涉及的代码内联,所以它可以检测你是否真的在修改参数,从而避免复制如果您的函数不修改参数。说到这里,你遇到的问题是什么?
我对 c/c++ 中的内联函数和参数复制有疑问。假设我想 运行 这个函数没有内联说明符:
void my_func(int param)
{
my_inner_func(param);
}
param 将首先复制到 my_func
,然后再复制到 my_inner_func
。如果函数 my_func
是 inline
,编译器会只为 my_inner_func
参数复制一次 param
还是两次。
我将不胜感激。
编辑:如果 c 和 c++ 有所不同,我想寻求解释。
C 和 C++ 都根据抽象机指定程序的行为。
my_func
的int param
存在于这个抽象机中,与my_inner_func
的int param
不同。他们有不同的身份。如果你取其中一个的地址和另一个的地址,它们保证比较不相等。
但是,如果您不获取其中任何一个的地址,则两者都不需要地址。
如果你对一个 int
所做的只是赋值或初始化它,然后用它来赋值或初始化另一个 int
,编译器可以证明没有定义的方式到达中间int
通过间接寻址(如指针),那么中间 int
不需要存在于实际目标机器上。
一些编译器在 link 时执行此操作时会遇到问题。其他人没有。
一些操作会阻止 int
的存在被删除。其他人不会。
我在您的示例中看不到任何需要中间 int
存在于目标机器上的内容。
inline
它只是编译器的一个 "suggestion",可以或不能 inline
你的函数。显然也可以选择 inline
一个你没有显式声明的函数 inline
.
换句话说,根据您的编译器和优化设置,您应该查看生成的汇编程序以获得答案。
只要遵循as if
规则,编译器就可以为所欲为。
规则规定,在任何时候你尝试测量程序的状态,它都会给出正确的答案。
在你不测量它的地方,它可以重新排序操作。
当编译器进行优化时,它将能够删除内联和非内联代码的第二个参数副本,除非有代码试图发现这一点。然后它必须生成符合假设规则的代码,并可能增加副本数。
视情况而定。内联函数(顺便说一句,最好让编译器决定是否执行此操作)必须公开与正常而非内联版本相同的可观察行为。所以最简单的方法是复制参数两次。编译器可能足够聪明,可以优化第二个副本如果内部函数不写入它。
如果函数不是内联的,在大多数体系结构上,函数调用本身的成本将明显高于复制 int
。
在寄存器中传递参数的系统上,用于传递单个 int
参数的寄存器在进入第一个函数时已经保存了值,它可以将它传递给下一个函数而无需创建新的复制.
不要为小事操心!
嗯,在内联函数中,编译器可以访问所有涉及的代码内联,所以它可以检测你是否真的在修改参数,从而避免复制如果您的函数不修改参数。说到这里,你遇到的问题是什么?