鱼C论坛

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

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

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

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

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

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

void func(void)
{
        static int count;
        printf("count=%d\n",count);
        count++;
}

int main (void)
{
        int i;
        for(i=0;i<10;i++)
        {
                func();
        }
return 0;
}
这个时候运行代码,将会获得如下的结果:
屏幕截图 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
就是这样,少上两个字,意思就完全不一样了
少上一个字,其实意思就完全不一样了
例如 ‘不’ 字
局部变量和静态局部变量完全不一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-12-31 17:50:00 | 显示全部楼层
应该是没有初始化的问题,初始化一下就行了
int count = 0;
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

让这个代码输出不正常,也非常容易,只需要把堆栈弄得乱七八糟就可以了
只需要随便调用上一个函数就可以了,下面的代码调用的是printf函数
sh-5.1$ cat main.c
#include <stdio.h>

void func(void) {
    int count;
    printf("count=%d\n", count);
    count++;
}

int main(void) {
    int i;
    for(i = 0; i < 10; i++) {
        printf("i=%d\n", i);           // 这个函数没有其他意思,就是为了弄乱堆栈,让堆栈中的值不再是0,不再保持之前的值
        func();
    }
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
main.c: In function ‘func’:
main.c:5:5: warning: ‘count’ is used uninitialized [-Wuninitialized]
    5 |     printf("count=%d\n", count);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:4:9: note: ‘count’ was declared here
    4 |     int count;
      |         ^~~~~
sh-5.1$ ./main
i=0
count=32538
i=1
count=32539
i=2
count=32540
i=3
count=32541
i=4
count=32542
i=5
count=32543
i=6
count=32544
i=7
count=32545
i=8
count=32546
i=9
count=32547
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-31 17:50:43 | 显示全部楼层
你看看你的test.c是否保存修改了,不带静态是不可能会累加的!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

void func(void) {
    int count;
    printf("count=%d\n", count);
    count++;
}

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

sh-5.1$ gcc -g -Wall -o main main.c
main.c: In function ‘func’:
main.c:5:5: warning: ‘count’ is used uninitialized [-Wuninitialized]
    5 |     printf("count=%d\n", count);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:4:9: note: ‘count’ was declared here
    4 |     int count;
      |         ^~~~~
sh-5.1$ ./main
count=0
count=1
count=2
count=3
count=4
count=5
count=6
count=7
count=8
count=9
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

那么也就是说,你这把gcc纠错开到最大,也只是出现了一个警告,对于程序的实际运行结果没有影响。那么这是为什么呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

反复确认过了,不带静态的时候发生了累加。所以才上来问的。刚刚学到这里,怕我哪里做的不对了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

?
3楼你看了吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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


编译器有点聪明,他会故意避开count的地址
我试了好多种方法,这样可以修改到count
sh-5.1$ cat main.c
#include <stdio.h>
#include <stdlib.h>

void fs(void) {
    int s = rand();
}

void func(void) {
    int count;
    printf("count=%d\n", count);
    count++;
}

int main(void) {
    int i;
    for(i = 0; i < 10; i++) {
        fs();
        func();
    }
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
main.c: In function ‘fs’:
main.c:5:9: warning: unused variable ‘s’ [-Wunused-variable]
    5 |     int s = rand();
      |         ^
main.c: In function ‘func’:
main.c:10:5: warning: ‘count’ is used uninitialized [-Wuninitialized]
   10 |     printf("count=%d\n", count);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:9:9: note: ‘count’ was declared here
    9 |     int count;
      |         ^~~~~
sh-5.1$ ./main
count=1804289383
count=846930886
count=1681692777
count=1714636915
count=1957747793
count=424238335
count=719885386
count=1649760492
count=596516649
count=1189641421
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

void func1(void);
void func2(void);
char string1,string2;
int var1,var2;

int main(void)
{
        printf("add of func1:%p\n",&func1);
        printf("add of func2:%p\n",&func2);
        printf("add of string1:%p\n",&string1);
        printf("add of string2:%p\n",&string2);
        printf("add of global_var1:%p\n",&var1);
        printf("add of golbal_var2:%p\n",&var2);
        func1();
        func2();


return 0;
}

void  func1(void)
{

        static int param1,param2;
        printf("add of func1_param1:%p\n",¶m1);
        printf("add of func1_parma2:%p\n",¶m2);
        static int var1,var2;
        printf("add of func1_static_var1:%p\n",&var1);
        printf("add of func1_static_var2:%p\n",&var2);

}
void  func2(void)
{
        const int param1,param2;
        printf("add of func2_const_param1:%p\n",¶m1);
        printf("add of func2_const_param2:%p\n",¶m2);
        printf("add of func2_var1:%p\n",&var1);
        printf("add of func2_var2:%p\n",&var2);
}
小甲鱼的例子里,在func1里定义了两个参数param1和param2,查询了地址,在func2里将这两个参数const后,存储地址没有表。而我的代码两次调用后,存储地址改变了。我很纳闷。
屏幕截图 2023-01-03 162944.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

int main(void) {
    int a = 3;      // a 初始化成3
    printf("%d\n", a);
    int b;          // b 没有初始化,值是随机的,有可能是0,也有可能是其他
    printf("%d\n", b);
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> 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
想知道小甲鱼最近在做啥?请访问 -> 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,看看是怎样规定的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

大佬,你这些英文资料都是从哪找到?能不能分享下
谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

谢谢,这两节,接触了太多的关键字,对于这些有点乱,我再自己捋一捋。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

谢谢您的回复
想知道小甲鱼最近在做啥?请访问 -> 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 无条件支持楼主!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-17 16:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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