鱼C论坛

 找回密码
 立即注册
查看: 2088|回复: 5

外部访问静态局部变量

[复制链接]
发表于 2021-8-4 03:36:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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

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

代码如下:

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


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


小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-8-4 08:30:28 From FishC Mobile | 显示全部楼层
这不是正道的光
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-4 08:33:14 From FishC Mobile | 显示全部楼层
而且,你直接返回static变量的指针不就行了吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-8-4 10:46:38 | 显示全部楼层
static 修饰局部变量会改变局部变量的存储位置
没有 static 的局部变量是存储在栈中的,添加了 static 以后,局部变量的存储位置就变成了全局存储区,变成了和变量 a,变量 p 一样了
test 函数中的变量 i 的地址是 0xffffcc0c
si 的地址是 0x100402014
全局变量 a 的地址是 0x100402010
可以看到 si 和 a 存放在一个区,因为两个变量的地址非常接近

  1. #include <stdio.h>

  2. int *p = NULL;
  3. int a = 456;

  4. void func(void) {
  5.     static int x = 0;
  6.     printf("%d\n", x);
  7.     p = &x;
  8. }

  9. void test(void) {
  10.     int i = 100;
  11.     static int si = 101;
  12.     printf("%p\n", &si);
  13.     printf("%p\n", &i);
  14. }

  15. int main()
  16. {
  17.     func();
  18.     *p = 123;
  19.     func();

  20.     printf("%p\n", &a);
  21.     test();
  22.     return 0;
  23. }
复制代码
  1. $ ./main
  2. 0
  3. 123
  4. 0x100402010
  5. 0x100402014
  6. 0xffffcc0c
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-8-4 13:09:04 | 显示全部楼层
  1. static int a = 0;
复制代码

之后生存期就不一样了啊 系统会保持这块地址不被使用
然后你设置了一个指针p指向这块地址 当然可以访问
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-5 13:43:34 | 显示全部楼层
人造人 发表于 2021-8-4 10:46
static 修饰局部变量会改变局部变量的存储位置
没有 static 的局部变量是存储在栈中的,添加了 static 以 ...

谢谢您,这下懂了,我还一直以为局部变量都会在栈里面的没想到用static关键字修饰之后会存储在全局变量的位置,难怪可以使用指针去访问到它。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-27 03:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表