局部变量:存放在栈空间,由系统自动分配以及自动释放,只在当前函数体内有效
- 局部变量的生命周期:只在当前函数体内有效,函数结束时,该空间的数据被系统自动释放
- 局部变量的定义:在 函数内部定义或者复合语句{}中定义的变量,都属于局部变量
- 局部变量的作用域:在 复合语句{}中有效
堆内存变量:存放在堆空间,由用户手动分配与手动释放,其生命周期由用户自定义
- 堆内存变量的生命周期:从malloc() / calloc() / realloc() 开始,一直到free()结束,由用户自定义
- 堆内存变量的定义:用户手动分配
- 堆内存的作用域:只要知道堆空间的首地址,都可以使用
数据段中的变量:存放在数据段中的变量,地址从高到低分别为:
.bss(对应未初始化的静态数据)
.data(已经初始化的静态变量->全局变量、static型静态变量)
.rodata(存放只读数据->常量)
- 全局变量:
- 全局变量的生命周期:整个程序中有效,直到程序结束
- 全局变量的定义:在函数体外 定义的变量
- 全局变量的作用域:在整个程序中有效,所有函数中有效
- 静态变量:
- 静态变量的生命周期:整个程序中有效,直到程序结束
- 静态变量的定义:加 static 关键词 修饰即可,如:static int a = 10;
- 静态变量的作用域:只在当前函数体内({}中),或当前文本(当前C文件)中有效。
- 注意:静态变量只能被初始化一次、静态全局变量只在当前文本(当前C文件)中有效。
下面用几个示例来演示 局部变量 、 全局变量 、 静态变量 、 堆内存变量 的区别。
#include
void fun(int a)
{
a = 20;
printf("a = %d\n",a);
printf("&a = %p\n",&a);
}
void main(int argc, char const *argv[])
{
int a = 10;
printf("a = %d\n",a);
{
int a = 20;
printf("==================\n");
printf("在复合语句{} 中:\n");
printf("int a = 20;\n");
printf("a = %d\n",a);
printf("&a = %p\n",&a);
printf("复合语句结束!\n");
printf("==================\n");
}
printf("a = %d\n",a);
printf("==================\n");
printf("main函数中:\n");
printf("a = %d\n",a);
printf("&a = %p\n",&a);
printf("调用fun函数:\n");
fun(a);
printf("调用函数结束:\n");
printf("a = %d\n",a);
printf("&a = %p\n",&a);
return ;
}
输出结果,如图所示:
可以发现在复合语句{}以及fun函数中的a的地址和main中的a的地址不同!
表明了在复合语句中{}以及 在函数中定义的变量,在复合语句结束、以及函数调用结束后,就会将其空间释放。
#include
#include
void main(int argc, char const *argv[])
{
//申请一块堆空间
int *p = (int *)malloc(sizeof(int) * 10);
int *source = p;
printf("source = %p\n",source);
int i;
for(i=0;i<10;i++)
{
p[i] = i;
printf("p[%d]= %d\n",i,p[i]);
}
printf("=======================\n");
printf("free(p)\n");
//释放堆空间
free(p);
printf("=======================\n");
printf("注意!目前为非法访问,十分危险\n");
for(i=0;i<10;i++)
{
printf("p[%d]= %d\n",i,p[i]);
}
return ;
}
输出结果,如图所示:
可以看见,将申请的堆空间给释放后,虽然其中存储的数据没有发生变化,但此时已经属于非法访问,因为你不知道下次再申请空间的时候,还会不会申请到同样地址的空间。
#include
int a = 10 ;
int b = 20;
void fun()
{
printf("在fun中:\n");
printf("a = %d,b = %d\n",a,b);
}
void main(int argc, char const *argv[])
{
int i=0;
printf("在main中:\n");
printf("a = %d,b = %d\n",a,b);
fun();
printf("用i将a,b的值交换\n");
i = a;
a = b;
b = i;
printf("在main中:\n");
printf("a = %d,b = %d\n",a,b);
fun();
return ;
}
#include
int a = 10 ;
int b = 20;
void fun()
{
printf("在fun中:\n");
printf("a = %d\n",a);
}
void main(int argc, char const *argv[])
{
int a = 20;
printf("int a = 20;\n");
printf("a = %d\n",a);
fun();
return;
}
输出结果,如图所示:
可以发现,全局变量在不同的函数内都有效,可以通过某一个函数将其的值改变,但要注意的是,当函数内出现同名变量的时候,优先使用函数内定义的变量。
#include
void main()
{
int i;
for(i=0;i<10;i++)
{
static int a = 0 ;
a++;
printf("a = %d\n",a);
}
printf("a = %d\n",a);
}
输出结果,如图所示:
编译时候,出现了这样的错误,其主要原因是第13行的 printf("a = %d",a); 给出来的信息,说是a没有定义。
这说明,静态局部变量的有效范围和局部变量一致。
当去除 printf("a = %d",a); 后,输出结果,如图所示:
则说明,静态变量只能初始化一次!
#include
static int a = 10;
void fun()
{
int k = 20 ;
a = k;
printf("函数fun内:\n");
printf("================\n");
printf("将20 赋值给a \n");
printf("a = %d\n",a);
printf("函数fun结束\n");
printf("================\n");
}
void main()
{
int i;
printf("a = %d\n",a);
fun();
printf("a = %d\n",a);
return;
}
输出结果,如图所示:
可以发现,静态全局变量与全局变量的效果是一样的,但是静态全局变量与全局变量的有个重要的区别
静态全局变量的作用域:只在当前文本(C文件)中有效
全局变量的作用域:在整个程序中有效