鱼C论坛

 找回密码
 立即注册
查看: 4612|回复: 20

[已解决]s1e33关于变量的生存期和存储类型的疑问

[复制链接]
发表于 2022-12-31 16:54:32 | 显示全部楼层 |阅读模式

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

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

x
在s1e32视频中,从8:55开始,小甲鱼使用一个例子讲解变量的静态存储期。当变量定义过程中,前面加了static后,局部变量具有静态存储期,在所在函数结束后不释放内存,一直到程序结束才释放。举例如下:
  1. #include<stdio.h>

  2. void func(void)
  3. {
  4.         static int count;
  5.         printf("count=%d\n",count);
  6.         count++;
  7. }

  8. int main (void)
  9. {
  10.         int i;
  11.         for(i=0;i<10;i++)
  12.         {
  13.                 func();
  14.         }
  15. return 0;
  16. }
复制代码

这个时候运行代码,将会获得如下的结果:
屏幕截图 2022-12-31 164728.jpg
而定义过程中,将static int count;改为int count;将会出现不同结果。
屏幕截图 2022-12-31 165045.jpg
但是我在自己的虚拟机上尝试两次编程过程的时候,一直是第一个结果,
屏幕截图 2022-12-31 165219.jpg
图片中间的vim命令上下分别是两次,带static和不带static的状态,结果是一样的。请问这是怎么回事?
最佳答案
2023-1-3 17:23:48
顶级太阳 发表于 2023-1-3 16:57
小甲鱼在s1e33的视频里9:37的时候明确说,变量被定义的时候,如果后面没有给出初始值的话,会被置0.
htt ...

学习就认真一点么
人家说的是静态局部变量,你可以再去听一遍
是加了static的局部变量才初始化成0
就是这样,少上两个字,意思就完全不一样了
少上一个字,其实意思就完全不一样了
例如 ‘不’ 字
局部变量和静态局部变量完全不一样
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-12-31 17:50:00 | 显示全部楼层
应该是没有初始化的问题,初始化一下就行了
  1. int count = 0;
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-31 17:50:42 | 显示全部楼层
main.c:5:5: warning: ‘count’ is used uninitialized [-Wuninitialized]

因为堆栈上面全是0,而且没有其他代码使用count这个变量的地址位置,所以一直保持上一次的值
所以才会出现 你截图的效果,我这边也和你的截图一样

让这个代码输出不正常,也非常容易,只需要把堆栈弄得乱七八糟就可以了
只需要随便调用上一个函数就可以了,下面的代码调用的是printf函数

  1. sh-5.1$ cat main.c
  2. #include <stdio.h>

  3. void func(void) {
  4.     int count;
  5.     printf("count=%d\n", count);
  6.     count++;
  7. }

  8. int main(void) {
  9.     int i;
  10.     for(i = 0; i < 10; i++) {
  11.         printf("i=%d\n", i);           // 这个函数没有其他意思,就是为了弄乱堆栈,让堆栈中的值不再是0,不再保持之前的值
  12.         func();
  13.     }
  14.     return 0;
  15. }
  16. sh-5.1$ gcc -g -Wall -o main main.c
  17. main.c: In function ‘func’:
  18. main.c:5:5: warning: ‘count’ is used uninitialized [-Wuninitialized]
  19.     5 |     printf("count=%d\n", count);
  20.       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
  21. main.c:4:9: note: ‘count’ was declared here
  22.     4 |     int count;
  23.       |         ^~~~~
  24. sh-5.1$ ./main
  25. i=0
  26. count=32538
  27. i=1
  28. count=32539
  29. i=2
  30. count=32540
  31. i=3
  32. count=32541
  33. i=4
  34. count=32542
  35. i=5
  36. count=32543
  37. i=6
  38. count=32544
  39. i=7
  40. count=32545
  41. i=8
  42. count=32546
  43. i=9
  44. count=32547
  45. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-31 17:50:43 | 显示全部楼层
你看看你的test.c是否保存修改了,不带静态是不可能会累加的!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-31 17:56:20 | 显示全部楼层
FengYue20 发表于 2022-12-31 17:50
你看看你的test.c是否保存修改了,不带静态是不可能会累加的!
  1. sh-5.1$ cat main.c
  2. #include <stdio.h>

  3. void func(void) {
  4.     int count;
  5.     printf("count=%d\n", count);
  6.     count++;
  7. }

  8. int main(void) {
  9.     int i;
  10.     for(i = 0; i < 10; i++) {
  11.         func();
  12.     }
  13.     return 0;
  14. }
  15. sh-5.1$ gcc --version
  16. gcc (GCC) 12.2.0
  17. Copyright (C) 2022 Free Software Foundation, Inc.
  18. This is free software; see the source for copying conditions.  There is NO
  19. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  20. sh-5.1$ gcc -g -Wall -o main main.c
  21. main.c: In function ‘func’:
  22. main.c:5:5: warning: ‘count’ is used uninitialized [-Wuninitialized]
  23.     5 |     printf("count=%d\n", count);
  24.       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. main.c:4:9: note: ‘count’ was declared here
  26.     4 |     int count;
  27.       |         ^~~~~
  28. sh-5.1$ ./main
  29. count=0
  30. count=1
  31. count=2
  32. count=3
  33. count=4
  34. count=5
  35. count=6
  36. count=7
  37. count=8
  38. count=9
  39. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-31 18:03:29 | 显示全部楼层

大佬,能否看一下我这道题:https://fishc.com.cn/forum.php?m ... p;page=1#pid6099234
为什么出了函数还能修改变量,不是应该弹栈了吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-1 08:03:26 | 显示全部楼层

那么也就是说,你这把gcc纠错开到最大,也只是出现了一个警告,对于程序的实际运行结果没有影响。那么这是为什么呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-1 08:28:56 | 显示全部楼层
FengYue20 发表于 2022-12-31 17:50
你看看你的test.c是否保存修改了,不带静态是不可能会累加的!

反复确认过了,不带静态的时候发生了累加。所以才上来问的。刚刚学到这里,怕我哪里做的不对了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-1 11:17:52 | 显示全部楼层
顶级太阳 发表于 2023-1-1 08:03
那么也就是说,你这把gcc纠错开到最大,也只是出现了一个警告,对于程序的实际运行结果没有影响。那么这 ...

?
3楼你看了吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-3 08:06:47 | 显示全部楼层

堆栈的事还不懂,以前没接触过这东西怎么弄。另外第3楼,每调用一次打印之外,输出的i值还是每调用一次增加1,没有出现调用后成为乱码呀。小甲鱼的例子很明显,每次调用函数的时候,count都会被重新置0,可是我的试验结果没有重置,你在第3楼的运行结果也显示了没有重新置0.
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-3 12:08:15 | 显示全部楼层
顶级太阳 发表于 2023-1-3 08:06
堆栈的事还不懂,以前没接触过这东西怎么弄。另外第3楼,每调用一次打印之外,输出的i值还是每调用一次增 ...


编译器有点聪明,他会故意避开count的地址
我试了好多种方法,这样可以修改到count

  1. sh-5.1$ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. void fs(void) {
  5.     int s = rand();
  6. }

  7. void func(void) {
  8.     int count;
  9.     printf("count=%d\n", count);
  10.     count++;
  11. }

  12. int main(void) {
  13.     int i;
  14.     for(i = 0; i < 10; i++) {
  15.         fs();
  16.         func();
  17.     }
  18.     return 0;
  19. }
  20. sh-5.1$ gcc -g -Wall -o main main.c
  21. main.c: In function ‘fs’:
  22. main.c:5:9: warning: unused variable ‘s’ [-Wunused-variable]
  23.     5 |     int s = rand();
  24.       |         ^
  25. main.c: In function ‘func’:
  26. main.c:10:5: warning: ‘count’ is used uninitialized [-Wuninitialized]
  27.    10 |     printf("count=%d\n", count);
  28.       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
  29. main.c:9:9: note: ‘count’ was declared here
  30.     9 |     int count;
  31.       |         ^~~~~
  32. sh-5.1$ ./main
  33. count=1804289383
  34. count=846930886
  35. count=1681692777
  36. count=1714636915
  37. count=1957747793
  38. count=424238335
  39. count=719885386
  40. count=1649760492
  41. count=596516649
  42. count=1189641421
  43. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-3 16:33:42 | 显示全部楼层
本帖最后由 顶级太阳 于 2023-1-3 16:34 编辑
人造人 发表于 2023-1-3 12:08
编译器有点聪明,他会故意避开count的地址
我试了好多种方法,这样可以修改到count


对于你写的这一段代码,我很不理解,每一次重新调用func函数的时候count应该是作为一个局部变量重新定义,这个时候应该是被置0的呀。
另外在做动动手第一个题目的时候,上面这个奇怪的问题又出现了。
  1. #include<stdio.h>

  2. void func1(void);
  3. void func2(void);
  4. char string1,string2;
  5. int var1,var2;

  6. int main(void)
  7. {
  8.         printf("add of func1:%p\n",&func1);
  9.         printf("add of func2:%p\n",&func2);
  10.         printf("add of string1:%p\n",&string1);
  11.         printf("add of string2:%p\n",&string2);
  12.         printf("add of global_var1:%p\n",&var1);
  13.         printf("add of golbal_var2:%p\n",&var2);
  14.         func1();
  15.         func2();


  16. return 0;
  17. }

  18. void  func1(void)
  19. {

  20.         static int param1,param2;
  21.         printf("add of func1_param1:%p\n",&param1);
  22.         printf("add of func1_parma2:%p\n",&param2);
  23.         static int var1,var2;
  24.         printf("add of func1_static_var1:%p\n",&var1);
  25.         printf("add of func1_static_var2:%p\n",&var2);

  26. }
  27. void  func2(void)
  28. {
  29.         const int param1,param2;
  30.         printf("add of func2_const_param1:%p\n",&param1);
  31.         printf("add of func2_const_param2:%p\n",&param2);
  32.         printf("add of func2_var1:%p\n",&var1);
  33.         printf("add of func2_var2:%p\n",&var2);
  34. }

复制代码

小甲鱼的例子里,在func1里定义了两个参数param1和param2,查询了地址,在func2里将这两个参数const后,存储地址没有表。而我的代码两次调用后,存储地址改变了。我很纳闷。
屏幕截图 2023-01-03 162944.jpg
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-3 16:38:44 | 显示全部楼层
count应该是作为一个局部变量重新定义,这个时候应该是被置0的呀。
局部变量如果你没有主动初始化的话,是不会初始化的
  1. #include <stdio.h>

  2. int main(void) {
  3.     int a = 3;      // a 初始化成3
  4.     printf("%d\n", a);
  5.     int b;          // b 没有初始化,值是随机的,有可能是0,也有可能是其他
  6.     printf("%d\n", b);
  7.     return 0;
  8. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-3 16:57:38 | 显示全部楼层
人造人 发表于 2023-1-3 16:38
count应该是作为一个局部变量重新定义,这个时候应该是被置0的呀。
局部变量如果你没有主动初始化的话,是 ...

小甲鱼在s1e33的视频里9:37的时候明确说,变量被定义的时候,如果后面没有给出初始值的话,会被置0.
https://www.bilibili.com/video/BV17s411N78s?p=33&vd_source=41936c8e78c2cb4425915e72a8f708cb
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-3 17:09:08 From FishC Mobile | 显示全部楼层
顶级太阳 发表于 2023-1-3 16:57
小甲鱼在s1e33的视频里9:37的时候明确说,变量被定义的时候,如果后面没有给出初始值的话,会被置0.
htt ...

我相信原文不是这么说的,或者有上下文。如果我猜错了,那小甲鱼就说错了。看看标准吧, http://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf 的 6.7.10.11,看看是怎样规定的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-3 17:23:48 | 显示全部楼层    本楼为最佳答案   
顶级太阳 发表于 2023-1-3 16:57
小甲鱼在s1e33的视频里9:37的时候明确说,变量被定义的时候,如果后面没有给出初始值的话,会被置0.
htt ...

学习就认真一点么
人家说的是静态局部变量,你可以再去听一遍
是加了static的局部变量才初始化成0
就是这样,少上两个字,意思就完全不一样了
少上一个字,其实意思就完全不一样了
例如 ‘不’ 字
局部变量和静态局部变量完全不一样
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-3 17:31:16 | 显示全部楼层
dolly_yos2 发表于 2023-1-3 17:09
我相信原文不是这么说的,或者有上下文。如果我猜错了,那小甲鱼就说错了。看看标准吧, http://www.open ...

大佬,你这些英文资料都是从哪找到?能不能分享下
谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-3 17:31:31 | 显示全部楼层
人造人 发表于 2023-1-3 17:23
学习就认真一点么
人家说的是静态局部变量,你可以再去听一遍
是加了static的局部变量才初始化成0

谢谢,这两节,接触了太多的关键字,对于这些有点乱,我再自己捋一捋。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-3 17:31:57 | 显示全部楼层
dolly_yos2 发表于 2023-1-3 17:09
我相信原文不是这么说的,或者有上下文。如果我猜错了,那小甲鱼就说错了。看看标准吧, http://www.open ...

谢谢您的回复
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-3 17:46:42 From FishC Mobile | 显示全部楼层
basketmn 发表于 2023-1-3 17:31
大佬,你这些英文资料都是从哪找到?能不能分享下
谢谢

这个资料就是 C 语言的标准(的 working draft),因为 C 语言的特点这应该是(除了正式的标准之外)最权威的 C 语言资料,所以涉及到这种语言本身的细节辨析就应该来这里找答案
直接搜索 C standard 就能找到了,还是很容易的

评分

参与人数 1荣誉 +2 鱼币 +2 收起 理由
basketmn + 2 + 2 无条件支持楼主!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-22 22:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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