访问在函数内声明的静态变量

时间:2017-05-01 13:23:35

标签: c gcc assembly objdump

我想知道为什么我们无法从函数外部访问那些在函数内部声明的变量?它在技术上可以访问它们,因为它们像全局/静态变量一样放入.data段。全局变量和静态全局变量之间有什么区别?

我有一个C文件如下:

int global_n =1;
static int global_static_n=2;

int main(){
    int local_n=3;
    static int local_static_n=4;
    return 0;
}

void test(){
    global_n=9;
    global_static_n=8;
    //local_n=7;
    //local_static_n=6;
}

我通过以下GCC命令编译并链接它:

gcc -Wall -m32 -nostdlib main.c -o main.o

我通过以下OBJDUMP命令对其进行反汇编:

objdump -w -j .text -D -Mi386,addr32,data32,intel main.o
objdump -w -s -j .data main.o

获得以下转储:

    Disassembly of section .text:

080480f8 <main>:
 80480f8:   55                      push   ebp
 80480f9:   89 e5                   mov    ebp,esp
 80480fb:   83 ec 10                sub    esp,0x10
 80480fe:   c7 45 fc 03 00 00 00    mov    DWORD PTR [ebp-0x4],0x3
 8048105:   b8 00 00 00 00          mov    eax,0x0
 804810a:   c9                      leave  
 804810b:   c3                      ret    

0804810c <test>:
 804810c:   55                      push   ebp
 804810d:   89 e5                   mov    ebp,esp
 804810f:   c7 05 00 a0 04 08 09 00 00 00   mov    DWORD PTR ds:0x804a000,0x9
 8048119:   c7 05 04 a0 04 08 08 00 00 00   mov    DWORD PTR ds:0x804a004,0x8
 8048123:   90                      nop
 8048124:   5d                      pop    ebp
 8048125:   c3 


Contents of section .data:

804a000 01000000 02000000 04000000

我可以看到local_static_n放入.data段,就像global_static_nglobal_n一样。如果我取消注释以下行,我将得到错误:

local_n=7;
local_static_n=6;
error: ‘local_n’ undeclared (first use in this function)
error: ‘local_static_n’ undeclared (first use in this function)

3 个答案:

答案 0 :(得分:3)

如果在命名空间作用域中使用static(即在函数和类之外),则相应的变量仅对此转换单元可见,而对于其他转换单元则不可见。此构造用于避免在不同翻译单元/库中定义的全局变量的无意名称冲突。这被称为“内部联系”

如果static用于函数中的变量,则此变量具有静态存储持续时间,但它仅在函数内部可见,而不在外部。

请注意,此“可见性”仅限制编译器在通过其名称访问变量时。当然,函数可以以其他方式返回或以其他方式公开static变量的地址;但是变量本身对于上述范围之外的编译器是不可见的。

答案 1 :(得分:1)

  

我想知道为什么我们不能从函数外部访问那些在函数内部声明的变量?技术上可以访问它们,因为它们像全局/静态变量一样放入.data段。

使其按照您希望的方式工作没有任何技术问题。然而,设计C语言的人特别不希望它以这种方式工作。这些限制是有目的的。

信息隐藏是一种通过明确限制对某些数据的访问来更容易推理程序的技术。这是如何做到这一点的一个例子。

答案 2 :(得分:0)

静态变量只能在声明的范围内访问。但是,如果您确实需要访问它们:

#include <stdio.h>

int global_n =1;
static int global_static_n=2;

void test(int* pStatic);

int main(){
    int local_n=3;
    static int local_static_n=4;
    printf("local static %d\n",local_static_n);
    test(&local_static_n);
    printf("local static %d\n",local_static_n);
    return 0;
}

void test(int* pStatic){
    *pStatic=5;
    global_n=9;
    global_static_n=8;
    //local_n=7;
    //local_static_n=6;
}

但是,不建议这样做。如果要访问静态变量,您可能应该将数据存储在不同的范围内,您的函数和其他代码可以访问它。