目录
1.作用域
作用域可以理解为在哪能调用,生命周期可以理解为什么时候销毁。
C语言作用域分为
- 代码块作用域(代码块是{}之间的一段代码)
- 函数作用域(其实就是形参+代码块)
- 文件作用域
1.1局部变量 静态局部变量
局部变量
局部变量一般定义在函数内和流程语句的{}内。
作用域和生命周期都伴随函数(函数执行完毕就会销毁该变量)
静态局部变量
static 修饰局部变量 作用域在函数内,但是生命周期伴随整个程序(程序停止了才会销毁该变量)
static int a 静态局部变量如果没有赋值默认值为0,只会在第一次调用时赋值默认值,当再次调用时变量值会在上次的值的基础上加减。
void val()
{
int a = 0
a++;
printf("[a]=[%d]",a);
}
void staticVal()
{
static int a;
/*static int a 静态局部变量如果没有赋值默认值为0,
只会在第一次调用时初始化赋值默认值,当再次调用时变量值会在上次的值的基础上加减。*/
a++;
printf("[a]=[%d]",a);
}
int main()
{
val();//输出1
val();//输出1
staticVal();//输出1
staticVal();//输出2
}
1.2全局变量 static全局变量
全局变量 | 静态全局变量 |
在函数外定义(非函数形参及函数{}内),可被本文件及其它文件中的函数所共用,若其它文件中的函数调用此变量,须用extern声明 | 在函数外定义(非函数形参及函数{}内),作用范围被限制在所定义的文件(.c文件)中 |
全局变量的生命周期和程序运行周期一样 | static全局变量的生命周期和程序(程序可以包括多个.c文件)运行周期一样,同时staitc全局变量的值只初始化一次 |
不同文件的全局变量不可重名 | 不同文件静态全局变量可以重名,但作用域不冲突 |
创建两个.c文件 mian.c first.c 用来演示全局变量和静态全局变量的作用域和声明周期
main.c
#include <stdio.h>
//定义全局变量g_num,全局变量没有赋值时默认为0
int g_num ;
//定义静态全局变量s_num,全局变量没有赋值时默认为0
static int s_num ;
int mian()
{
printf("a=%d",a);
}
first.c
//g_num是main.c定义的全局变量,在其他文件的使用这个全局变量需要extern声明;
//全局变量的作用域是整个程序所以整个程序只有这么一个唯一的g_num,不能重复定义
extern int g_num;
//定义静态全局变量s_num,静态全局变量的作用域是当前文件所以可以同名重定义
static int s_num ;
void()
{
// 全局变量作用域是整个程序所以其他文件声明后是可以访问的;
printf("g_num =%d",g_num);
//Err 静态全局变量的作用域是静态全局变量所定义的文件,其他文件访问回报错的
printf("s_num =%d",s_num);
}
1.3 全局函数和静态函数
在C语言中函数默认都是全局的,正常定义的函数就是全局函数。
使用关键字static可以将函数声明为静态,函数定义为static就意味着这个函数只能在定义这个函数的文件中使用,在其他文件中不能调用,即使在其他文件中声明这个函数都没用。 对于不同文件中的 static 函数名字可以相同。
mian.c
#include <stdio.h>
//调用其他文件的函数,首先声明
extern int geti();
int mian()
{
geti(); //调用其他文件函数geti()
geto();//Err 其他文件的静态函数不能访问
}
get.c
//全局函数 ---除了本文件外的其他文件extern声明后也可以访问
int geti()
{
printf("sssssss");
return 0;
}
//静态函数 ----只有本文件内可以访问
static int geto()
{
printf("aaaaa");
return 0;
}
2.内存布局
2.1. 栈区
存放内容:
- 临时创建的局部变量和const定义的局部变量存放在栈区。
- 函数调用和返回时,其入口参数和返回值存放在栈区。
栈区介绍
- 栈区由编译器自动分配释放,由操作系统自动管理,无须手动管理。
- 栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。
- 栈区按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
- 栈区是后进先出原则,即先进去的被堵在屋里的最里面,后进去的在门口,释放的时候门口的先出去。
2.2 堆区 malloc()
堆区介绍 由程序员分配内存和释放。 有申请就一定要释放 不释放则造成内存泄漏
存放内容 调用函数 malloc()和free( ).
用malloc等函数实现动态分布内存。
void *malloc(size_t);
参数size_t是分配的字节大小。
返回值是一个void*型的指针,该指针指向分配空间的首地址。
(void *型指针可以任意转换为其他类型的指针)例如: int* ptr = int *malloc(1024);
free(ptr) ;
用free函数进行内存释放,否则会造成内存泄漏。
void free(void * /*ptr*/);
参数是开辟的内存的首地址。
2.3 全局(静态)区
全局(静态)区介绍
通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。
全局区有 .bss段 和 .data段组成,可读可写。
.bss段
- 未初始化的全局变量和未初始化的静态变量存放在.bss段。
- 初始化为0的全局变量和初始化为0的静态变量存放在.bss段。
- .bss段不占用可执行文件空间,其内容由操作系统初始化。
.data段
- 已初始化的全局变量存放在.data段。
- 已初始化的静态变量存放在.data段。
- .data段占用可执行文件空间,其内容有程序初始化。
2.4 常量区
- 字符串、数字等常量存放在常量区。
- const修饰的全局变量存放在常量区。
- 程序运行期间,常量区的内容不可以被修改。
2.5 代码区
- 程序执行代码存放在代码区,其值不能修改(若修改则会出现错误)。
- 字符串常量和define定义的常量也有可能存放在代码区。
内存污染:对没有申请的内容地址进行修改;
参考文章:
https://blog.csdn.net/MQ0522/article/details/114823770