s1e33关于变量的生存期和存储类型的疑问
在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;
}
这个时候运行代码,将会获得如下的结果:
而定义过程中,将static int count;改为int count;将会出现不同结果。
但是我在自己的虚拟机上尝试两次编程过程的时候,一直是第一个结果,
图片中间的vim命令上下分别是两次,带static和不带static的状态,结果是一样的。请问这是怎么回事? 应该是没有初始化的问题,初始化一下就行了
int count = 0; 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$
你看看你的test.c是否保存修改了,不带静态是不可能会累加的! 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$
人造人 发表于 2022-12-31 17:56
大佬,能否看一下我这道题:https://fishc.com.cn/forum.php?mod=viewthread&tid=222692&page=1#pid6099234
为什么出了函数还能修改变量,不是应该弹栈了吗? 人造人 发表于 2022-12-31 17:56
那么也就是说,你这把gcc纠错开到最大,也只是出现了一个警告,对于程序的实际运行结果没有影响。那么这是为什么呢?
FengYue20 发表于 2022-12-31 17:50
你看看你的test.c是否保存修改了,不带静态是不可能会累加的!
反复确认过了,不带静态的时候发生了累加。所以才上来问的。刚刚学到这里,怕我哪里做的不对了。 顶级太阳 发表于 2023-1-1 08:03
那么也就是说,你这把gcc纠错开到最大,也只是出现了一个警告,对于程序的实际运行结果没有影响。那么这 ...
?
3楼你看了吗?
人造人 发表于 2023-1-1 11:17
?
3楼你看了吗?
堆栈的事还不懂,以前没接触过这东西怎么弄。另外第3楼,每调用一次打印之外,输出的i值还是每调用一次增加1,没有出现调用后成为乱码呀。小甲鱼的例子很明显,每次调用函数的时候,count都会被重新置0,可是我的试验结果没有重置,你在第3楼的运行结果也显示了没有重新置0. 顶级太阳 发表于 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$
本帖最后由 顶级太阳 于 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;
}
voidfunc1(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);
}
voidfunc2(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后,存储地址没有表。而我的代码两次调用后,存储地址改变了。我很纳闷。
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;
}
人造人 发表于 2023-1-3 16:38
count应该是作为一个局部变量重新定义,这个时候应该是被置0的呀。
局部变量如果你没有主动初始化的话,是 ...
小甲鱼在s1e33的视频里9:37的时候明确说,变量被定义的时候,如果后面没有给出初始值的话,会被置0.
https://www.bilibili.com/video/BV17s411N78s?p=33&vd_source=41936c8e78c2cb4425915e72a8f708cb 顶级太阳 发表于 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,看看是怎样规定的 顶级太阳 发表于 2023-1-3 16:57
小甲鱼在s1e33的视频里9:37的时候明确说,变量被定义的时候,如果后面没有给出初始值的话,会被置0.
htt ...
学习就认真一点么
人家说的是静态局部变量,你可以再去听一遍
是加了static的局部变量才初始化成0
就是这样,少上两个字,意思就完全不一样了
少上一个字,其实意思就完全不一样了
例如 ‘不’ 字
局部变量和静态局部变量完全不一样
dolly_yos2 发表于 2023-1-3 17:09
我相信原文不是这么说的,或者有上下文。如果我猜错了,那小甲鱼就说错了。看看标准吧, http://www.open ...
大佬,你这些英文资料都是从哪找到?能不能分享下
谢谢 人造人 发表于 2023-1-3 17:23
学习就认真一点么
人家说的是静态局部变量,你可以再去听一遍
是加了static的局部变量才初始化成0
谢谢,这两节,接触了太多的关键字,对于这些有点乱,我再自己捋一捋。 dolly_yos2 发表于 2023-1-3 17:09
我相信原文不是这么说的,或者有上下文。如果我猜错了,那小甲鱼就说错了。看看标准吧, http://www.open ...
谢谢您的回复 basketmn 发表于 2023-1-3 17:31
大佬,你这些英文资料都是从哪找到?能不能分享下
谢谢
这个资料就是 C 语言的标准(的 working draft),因为 C 语言的特点这应该是(除了正式的标准之外)最权威的 C 语言资料,所以涉及到这种语言本身的细节辨析就应该来这里找答案
直接搜索 C standard 就能找到了,还是很容易的
页:
[1]
2