C 内联函数中名称冲突的局部变量

C 内联函数中名称冲突的局部变量,c,scope,semantics,static-variables,C,Scope,Semantics,Static Variables,我试图研究内联的复杂性。为此,我创建了这个小程序。我定义了一个内联函数,它有一个与全局定义变量同名的“自动”变量。在确保我的函数被标记为static(以满足C99标准)之后,我正在研究使用objdump创建的可执行文件。但首先,这是我的计划 #include <stdio.h> #include <stdlib.h> int AAAABBBB = 5; //global scope #define DOINLINE$ #ifdef DOINLINE static i

我试图研究
内联
的复杂性。为此,我创建了这个小程序。我定义了一个内联函数,它有一个与全局定义变量同名的“自动”变量。在确保我的函数被标记为
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;
}
#包括
#包括
int aabbbb=5//全球范围
#定义DOINLINE$
#ifdef DOINLINE
静态内联void uuu属性uuu((始终内联))myfunc(){
#否则
void myfunc(){
#恩迪夫
静态int-aabbbb=6;
printf(“全局现在是%d\n”,aabbbbbb);
}
int main(){
printf(“全局为%d\n”,aabbbbbb);
myfunc();
printf(“全局现在是%d\n”,aabbbbbb);
返回0;
}
此函数按预期工作,这些看似冲突的名称之间没有任何冲突。但是,查看可执行文件的对象转储(以及对象文件),我发现编译器确实满足了我的请求,并且没有单独的
myfunc
部分

下面是的粘贴。我确信
myfunc
中的局部变量埋在其中的某个地方,但似乎无法确定它在哪里


将函数局部变量声明为非静态似乎毫无意义。

myfunc
中定义的
aaaaabbb
不会出现在目标文件中,因为编译器对其进行了优化。我们可以在
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 1154:be 06 00 mov esi,0x6 1159:48 8d 3d b2 0e 00 lea rdi,[rip+0xeb2]#2012 1160:B800 mov eax,0x0 1165:e8 c6 fe ff ff呼叫1030 在这里,我们看到编译器只是将6直接传递给
printf
;它从未存储在内存中。
myfunc
中的
aaaabbb
在对象文件中除此之外不存在

有人可能想知道,在优化过程中,编译器如何删除静态对象(该对象本应存在于整个程序执行过程中)。C标准规定,实际上,C实现可以以任何方式优化程序,但不会改变可观察到的行为,即:

  • 对易失性对象的访问进行严格评估
  • 当程序结束时,写入文件的数据与定义一致
  • 与交互设备(如终端)的交互如“文件”条款所规定

因为是否将静态(但不是易失性)对象的数据写入内存不是可观察行为的一部分(而实际上是否有可观察行为的内存),编译器可以在优化过程中自由删除它。

myfunc
中定义的
aaaaaabbb
不会出现在目标文件中,因为编译器将其优化掉。我们可以在
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 1154:be 06 00 mov esi,0x6 1159:48 8d 3d b2 0e 00 lea rdi,[rip+0xeb2]#2012 1160:B800 mov eax,0x0 1165:e8 c6 fe ff ff呼叫1030 在这里,我们看到编译器只是将6直接传递给
printf
;它从未存储在内存中。
myfunc
中的
aaaabbb
在对象文件中除此之外不存在

有人可能想知道,在优化过程中,编译器如何删除静态对象(该对象本应存在于整个程序执行过程中)。C标准规定,实际上,C实现可以以任何方式优化程序,但不会改变可观察到的行为,即:

  • 对易失性对象的访问进行严格评估
  • 当程序结束时,写入文件的数据与定义一致
  • 与交互设备(如终端)的交互如“文件”条款所规定

因为是否将静态(但不是易失性)对象的数据写入内存不是可观察行为的一部分(而实际上是否有可观察行为的内存)在编译过程中,编译器可以自由地删除它。

为什么你认为存在冲突?本地名称阴影全局名称,这是C++的规则。无论你声明函数是否内联都是正确的。你似乎认为内联作品是某种宏,用函数的文本替代你的源代码,但这不是。这是一个案例。你想知道C++和C++之间的区别,或者为什么你要使用这两个标签?所以…你的问题是什么?在转储中我的局部变量在哪里?C和C++之间有区别吗?@ HunnFald大概已经被优化了。你认为有什么冲突。为什么你会认为有一个冲突?本地名字是影子的全局名字,这是C++的规则。你声明函数是否是内联是正确的。你似乎认为内联作品是某种宏,用函数的文本替代你的源代码,但事实并非如此。Ant知道C和C++之间的区别,或者为什么你使用这两个标签?那么…你的问题是什么?在转储中我的局部变量在哪里?C和C++之间有区别吗?@ HunnFald大概是被优化了的。C和C++都不知道编译器应该如何生成目标代码。只要对象代码做了什么,我应该做什么。允许。那么这是本地内联变量的标准GCC行为吗?静态对它没有影响吗?如果我多次这样称呼它会怎么样?@HighOnMeat: