彼岸境 发表于 2021-8-4 03:36:40

外部访问静态局部变量

我自己在看小甲鱼的视频 -> 带你学C带你飞的系列课程后,发现了一个问题,有点不懂,还希望大家多多帮忙解读

在带你学C带你飞的P33 生存期和存储类型这一集中,小甲鱼提到了 static 关键字可以用来修饰局部变量使其变为静态存储器,但它仍然是一个局部变量仍然是代码块作用域,外部无法访问该变量

不过我就自己不信邪,自己瞎整了一下,居然在外部成功访问了这个静态局部变量。

代码如下:

#include <stdio.h>
#define aa (*((int *)p))    // 将全局变量p转换为一个整型指针并解引用得到一个可以用于存储的空间
long int p = 0;    // 定义一个全局变量用于接收局部变量的地址值, 使用long int类型是为了避免一些错误
void func(void);
void func(void)
{
    static int a = 0;
    p = (long int)(&a);    // 将地址值赋值给全局变量p
    printf("%d\n", a++);
}
int main(void)
{
    int i = 0;
    for(i = 0; i < 10; i++)
    {
      func();
    }
    aa = 2;    // 在外部尝试修改静态局部变量的值
    printf("%d\n", aa);    // 在外部尝试打印静态局部变量的值
    func();    // 再次尝试调用函数验证局部变量是否被改变
    return 0;
}

编译的时候虽然有很多警告,但是并没有报错,程序可以正常跑起来
运行结果:
PS D:\C语言> gcc .\实验.c
.\实验.c: In function 'func':
.\实验.c:9:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   p = (long int)(&a);
         ^
.\实验.c: In function 'main':
.\实验.c:2:15: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
#define aa (*((int *)p))
               ^
.\实验.c:20:5: note: in expansion of macro 'aa'
   aa = 2;
   ^
.\实验.c:2:15: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
#define aa (*((int *)p))
               ^
.\实验.c:21:20: note: in expansion of macro 'aa'
   printf("%d\n", aa);
                  ^
PS D:\C语言> .\a.exe   
0
1
2
3
4
5
6
7
8
9
2
2


赚小钱 发表于 2021-8-4 08:30:28

这不是正道的光

赚小钱 发表于 2021-8-4 08:33:14

而且,你直接返回static变量的指针不就行了吗

人造人 发表于 2021-8-4 10:46:38

static 修饰局部变量会改变局部变量的存储位置
没有 static 的局部变量是存储在栈中的,添加了 static 以后,局部变量的存储位置就变成了全局存储区,变成了和变量 a,变量 p 一样了
test 函数中的变量 i 的地址是 0xffffcc0c
si 的地址是 0x100402014
全局变量 a 的地址是 0x100402010
可以看到 si 和 a 存放在一个区,因为两个变量的地址非常接近

#include <stdio.h>

int *p = NULL;
int a = 456;

void func(void) {
    static int x = 0;
    printf("%d\n", x);
    p = &x;
}

void test(void) {
    int i = 100;
    static int si = 101;
    printf("%p\n", &si);
    printf("%p\n", &i);
}

int main()
{
    func();
    *p = 123;
    func();

    printf("%p\n", &a);
    test();
    return 0;
}

$ ./main
0
123
0x100402010
0x100402014
0xffffcc0c

万千只cnm 发表于 2021-8-4 13:09:04

static int a = 0;
之后生存期就不一样了啊 系统会保持这块地址不被使用
然后你设置了一个指针p指向这块地址 当然可以访问

彼岸境 发表于 2021-8-5 13:43:34

人造人 发表于 2021-8-4 10:46
static 修饰局部变量会改变局部变量的存储位置
没有 static 的局部变量是存储在栈中的,添加了 static 以 ...

谢谢您,这下懂了,我还一直以为局部变量都会在栈里面的没想到用static关键字修饰之后会存储在全局变量的位置,难怪可以使用指针去访问到它。
页: [1]
查看完整版本: 外部访问静态局部变量