内联函数中名称冲突的局部变量
local variable with conflicting name in inline function
我正在尝试研究 inline
的复杂性。为此,我创建了这个小程序。我已经定义了一个内联函数,它有一个与全局定义变量同名的 'automatic' 变量。在确保我的函数被标记为 static
(以满足 C99 标准)之后,我正在研究使用 objdump 创建的可执行文件。但首先,这是我的程序
#include <stdio.h>
#include <stdlib.h>
int AAAABBBB = 5; //global scope
#define DOINLINE$
#ifdef DOINLINE
static inline void __attribute__((always_inline)) myfunc() {
#else
void myfunc() {
#endif
static int AAAABBBB = 6;
printf("global is now %d\n", AAAABBBB);
}
int main() {
printf("global is %d\n", AAAABBBB);
myfunc();
printf("global is now %d\n", AAAABBBB);
return 0;
}
此函数按预期工作,并且在这些看似冲突的名称之间没有任何冲突。但是,查看可执行文件(以及目标文件)的对象转储,我发现编译器确实满足了我的要求,并且 myfunc
.
没有单独的部分
这是 objdump 的粘贴。我确定 myfunc
中的局部变量被埋在其中的某个地方,但似乎无法弄清楚它在哪里。
备注
将函数局部变量声明为非静态似乎完全没有意义。
myfunc
里面定义的AAAABBBB
没有出现在目标文件中,因为编译器把它优化掉了。我们可以在 main
的反汇编中看到这一点,这是由内联 myfunc
:
产生的代码
1154: be 06 00 00 00 mov esi,0x6
1159: 48 8d 3d b2 0e 00 00 lea rdi,[rip+0xeb2] # 2012
1160: b8 00 00 00 00 mov eax,0x0
1165: e8 c6 fe ff ff call 1030
这里我们看到编译器只是把6直接传给了printf
;它从未存储在内存中。 myfunc
中的AAAABBBB
除此之外在目标文件中不存在。
有人可能想知道编译器如何在优化过程中删除本应在整个程序执行过程中存在的静态对象。 C 标准说,实际上,C 实现可以以任何不改变可观察行为的方式优化程序,即:
- 对易失性对象的访问被严格评估。
- 程序结束时,写入文件的数据如定义。
- 与交互式设备(例如终端)的交互在“文件”子句中指定。
由于静态(但不是易失性)对象的数据是否写入内存不是可观察行为的一部分(并且是否真的有内存根本不是可观察行为),编译器可以自由地在优化期间将其删除。
我正在尝试研究 inline
的复杂性。为此,我创建了这个小程序。我已经定义了一个内联函数,它有一个与全局定义变量同名的 'automatic' 变量。在确保我的函数被标记为 static
(以满足 C99 标准)之后,我正在研究使用 objdump 创建的可执行文件。但首先,这是我的程序
#include <stdio.h>
#include <stdlib.h>
int AAAABBBB = 5; //global scope
#define DOINLINE$
#ifdef DOINLINE
static inline void __attribute__((always_inline)) myfunc() {
#else
void myfunc() {
#endif
static int AAAABBBB = 6;
printf("global is now %d\n", AAAABBBB);
}
int main() {
printf("global is %d\n", AAAABBBB);
myfunc();
printf("global is now %d\n", AAAABBBB);
return 0;
}
此函数按预期工作,并且在这些看似冲突的名称之间没有任何冲突。但是,查看可执行文件(以及目标文件)的对象转储,我发现编译器确实满足了我的要求,并且 myfunc
.
这是 objdump 的粘贴。我确定 myfunc
中的局部变量被埋在其中的某个地方,但似乎无法弄清楚它在哪里。
备注
将函数局部变量声明为非静态似乎完全没有意义。
myfunc
里面定义的AAAABBBB
没有出现在目标文件中,因为编译器把它优化掉了。我们可以在 main
的反汇编中看到这一点,这是由内联 myfunc
:
1154: be 06 00 00 00 mov esi,0x6 1159: 48 8d 3d b2 0e 00 00 lea rdi,[rip+0xeb2] # 2012 1160: b8 00 00 00 00 mov eax,0x0 1165: e8 c6 fe ff ff call 1030
这里我们看到编译器只是把6直接传给了printf
;它从未存储在内存中。 myfunc
中的AAAABBBB
除此之外在目标文件中不存在。
有人可能想知道编译器如何在优化过程中删除本应在整个程序执行过程中存在的静态对象。 C 标准说,实际上,C 实现可以以任何不改变可观察行为的方式优化程序,即:
- 对易失性对象的访问被严格评估。
- 程序结束时,写入文件的数据如定义。
- 与交互式设备(例如终端)的交互在“文件”子句中指定。
由于静态(但不是易失性)对象的数据是否写入内存不是可观察行为的一部分(并且是否真的有内存根本不是可观察行为),编译器可以自由地在优化期间将其删除。