C语言内存管理

本文详细解释了C语言中的作用域规则,包括局部变量、静态局部变量和全局变量的区别,以及它们的生命周期。此外,还介绍了内存布局,如栈区、堆区、全局(静态)区、常量区和代码区的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.作用域

1.1局部变量 静态局部变量

 1.2全局变量 static全局变量

 1.3 全局函数和静态函数

2.内存布局

2.1. 栈区

2.2 堆区   malloc()

2.3 全局(静态)区

2.4 常量区

2.5 代码区


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定义的局部变量存放在栈区
  • 函数调用和返回时,其入口参数返回值存放在栈区

栈区介绍

  1. 栈区由编译器自动分配释放,由操作系统自动管理,无须手动管理。
  2. 栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁
  3. 栈区按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
  4. 栈区是后进先出原则,即先进去的被堵在屋里的最里面,后进去的在门口,释放的时候门口的先出去。

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值