在C语言中,我们总是动不动就int a , int b , char c的,就像创造一个个小人一样,看似他们无拘无束,咱们造出来就管不着了。
实则,他们有着自己的寿命(生命周期),有着自己的活动范围(作用域),有着自己的国籍(链接属性),同时我们也能够通过移动变量位置和static、extern等关键字来管理他们。
总表
在这里也是直接为大家提供参考的总表,接下来我们用一个个程序来验证他们。
内存区域
在C语言所管理的内存中,我们大致可以抽象理解成为代码区、全局(静态)变量区、栈区、堆区。
代码区可以用以存储函数、全局(静态)变量区用以存储全局变量以及静态变量、栈区用以存储自定函数内部非静态的局部变量,堆区用以存储开发人员手动开辟的内存区域。
这里需要注意的全局(静态)变量区会将未初始化的变量全部自动赋值为0
实验测试
普通局部变量与静态局部变量:
一个非主函数的内部定义的变量可以称之为局部变量,未加static的局部变量为普通局部变量,反之为静态局部变量。
普通局部变量在函数结束时即释放,而静态变量则不会:
我们也必须注意到其中的一个细节:静态局部变量若未给出初值,将会自动赋0值
普通局部变量未给出初值会被赋随机值,因VS保护机制此实验略。
其实在静态局部变量这里也会有一个好玩的现象:
好的,你会发现我们多次进入函数func,但是在最初的static int s_part = 1;的语句并不会将s_part重新赋值为1,在这里,我们可以理解为已定义的静态局部变量进入函数后会直接忽视定义语句,直接执行下一语句。
但是,请注意,我们的局部函数是是无法被外部函数看到的:
普通全局变量与静态全局变量:
全局变量在函数外部声明定义,不给出初值直接自动赋值为0。
普通全局变量加上static关键字会出现怎么样的变化呢?这其实需要两个文件来体现:
我们多添加一个temp.cpp文件,然后开干
在temp.cpp中加入两个全局变量的定义,然后我们到主函数程序中来尝试使用这两个全局变量。
我们十分轻松的便使用到了另一个文件里的gloal,但若是加了static的s_gloal呢;
VS直接干脆利落的报错。
而若在声明位置加上static连编译也通不过了。
我们也不难理解,static 将普通全局变量的默认链接属性外部修改为了内部,仅限一个文件内部使用。
动态内存 :
我们手动开辟的内存能不能给其他的文件使用呢?
答案是可以,但是我们不能说动态内存的链接属性是外部的,实际上我们是将动态内存地址给了一个全局指针,而我们在另一个文件中声明这个指针进行使用,是这个指针的链接属性是外部的,而并非动态内存能够外部链接,它不具备链接属性。
普通函数与静态函数 :
与之前的普通转静态相似,静态函数只需直接将static加到函数返回值之前就实现了一个静态函数的声明。
接下来我们尝试在另一个文件里进行调用:
不加static编译器不报错,但运行时报错。
添加了static则会在编译时报错。
编译与运行的结果与我们的普通全局变量和静态全局变量相同。
可见,static同样将默认链接属性为外部的普通函数修改为了内部。
实验调试代码(供以验证)
temp.cpp
#include<stdlib.h>
#include<stdio.h>
//int gloal=10;
//static int s_gloal=20;
//int* m_a = (int*)malloc(sizeof(int));
void func1()
{
printf("this is a normal func\n");
}
static void func2()
{
printf("this is a static func\n");
}
源.cpp
#include<stdio.h>
#include<stdlib.h>
#if 0
void func()
{
static int s_part = 1;
int part = 0;
printf("s_part=%d\n",s_part);
s_part++;
}
int main()
{
func();
func();
func();
func();
printf("part= %d , s_part = %d\n", part, s_part);
return 0;
}
#endif
#if 0
extern int gloal;
extern /*static*/ int s_gloal;
void func()
{
printf("gloal = %d, s_gloal = %d \n", gloal, s_gloal );
}
int main()
{
func();
printf("gloal = %d, s_gloal = %d \n", gloal, s_gloal);
return 0;
}
#endif
#if 0
extern int* m_a;
int main()
{
*m_a = 1;
printf("m_a = %d", *m_a);
free(m_a);
return 0;
}
#endif
#if 1
extern void func1();
extern static void func2();
int main()
{
func1();
func2();
return 0;
}
#endif