C语言内存学习

  1. 在c语言中内存包括 堆内存、栈内存、全局常态区、常量区
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  2. 变量分为:
    按存储类别分为自动变量、静态变量、寄存器变量(不在主存中,而在 CPU 寄存器里)、外部变量
    按作用域分类:局部变量、全局变量、形参
    按生命周期分类:自动存储期、静态存储期、动态存储期
    按数据类型分类:基本类型、派生类型、空类型

  3. 存储类别
    在这里插入图片描述
    在这里插入图片描述

    4.1. 自动变量(Automatic)

void func() {
    int x = 10;        // 等价于 auto int x = 10;   存放在栈上
    char c;            // 未初始化 → 垃圾值!
}

auto(通常省略),存储在栈(stack),函数调用时分配,函数返回时自动释放,不会自动初始化 → 值为垃圾数据
4.2. 静态变量(Static)

// 全局静态(仅本文件可见)
static int global_count = 0;   // → .data 段

void counter() {
    static int local_count = 0; // 只初始化一次,函数退出不销毁   → .bss 段(值为 0)
    local_count++;
    static char msg[] = "Hi";    // → .data 段(含字符串)
    printf("%d\n", local_count);
}

.bss(Block Started by Symbol)段不占可执行文件空间,运行时由 OS 清零。
全局静态变量(文件作用域 + static)
局部静态变量(函数内 + static)
如果显式初始化(如 = 5)→ 已初始化数据段(.data)
如果未初始化或初始化为 0 → 未初始化数据段(.bss)
存储在数据段(.data 或 .bss)
程序启动时分配,结束时释放
自动初始化为 0(即使你没写)
生命周期贯穿整个程序

4.3. 外部变量(External)

// file1.c
int global_var = 42; // 定义(分配内存)// 定义 → .data 段

// file2.c
extern int global_var; // 声明(不分配内存,引用 file1.c 的变量)

外部变量和普通全局变量内存位置相同,extern 只是“告诉编译器这个变量在别处定义”。
本质:就是全局变量,只是用 extern 在其他文件中声明
内存位置:
显式初始化 → .data 段
未初始化 → .bss 段

4.4. 寄存器变量(Register)

register int i; // 建议编译器将 i 放入 CPU 寄存器(加速访问)

⚠️ 现代编译器优化能力强,通常忽略 register,且不能取地址(&i 非法)
编译器可能忽略该请求(现代优化器自行决定)
不能取地址(&x 非法)→ 因为寄存器没有内存地址
访问速度最快(比栈快得多)
补充:
在这里插入图片描述
局部变量 → 用自动变量(栈):高效、安全
需要保持状态 → 用 static:避免全局污染
跨文件共享 → 用 extern + 全局变量:谨慎使用
不要滥用 register:让编译器优化
永远初始化局部变量:避免栈上的垃圾值
5. 作用域
在这里插入图片描述
全局变量默认具有外部链接性(可被其他文件通过 extern 访问),加 static 可变为内部链接性(仅本文件可见)。
局部变量 栈区(Stack)
全局变量 已初始化的全局变量:存储在 .data 段(初始化数据段)。
未初始化或初始化为零的全局变量:存储在 .bss 段(未初始化数据段,程序启动时自动清零)。
形参(形式参数)栈区(Stack)
在这里插入图片描述

  1. 生命周期
    在这里插入图片描述
    在这里插入图片描述
    栈溢出:栈区空间有限(通常几MB),递归过深或局部变量过大可能导致栈溢出。
    内存泄漏:动态分配的内存未释放会导致泄漏,长期运行的程序可能因此崩溃。
    野指针:释放堆内存后未置空指针,再次访问会导致未定义行为。
    静态变量的初始化:静态局部变量仅在第一次进入作用域时初始化,后续调用保留值。
  2. 数据类型
    在这里插入图片描述
int age;           // 基本类型
char name[20];     // 数组(派生)
struct Point p;    // 结构体(派生)
void *ptr;         // void 指针
  1. 对比
    在这里插入图片描述
    优先使用局部变量(减少全局状态,提高模块化)
    全局变量加 static(除非明确需要跨文件共享)
    局部变量务必初始化(避免垃圾值)
    慎用 register(让编译器优化)
    动态内存用 malloc/free(不属于“变量种类”,但需手动管理)
#include <stdio.h>

static int global_static = 100; // 全局、静态存储期、内部链接

void func() {
    auto int local_auto = 200;   // 局部、自动存储期(auto 可省略)
    static int local_static = 300; // 局部作用域,静态存储期
    
    printf("local_static = %d\n", local_static);
    local_static++; // 下次调用会保留值
}

int main() {
    func(); // 输出 300
    func(); // 输出 301
    return 0;
}

栈:主要用于存储局部变量(无论是基本类型还是派生类型),随着函数调用进入和退出而自动分配和回收。
数据段:用于存储全局变量和静态变量,这些变量在程序运行期间一直存在。
堆:用于动态内存分配,适用于那些需要在运行时确定大小的数据结构。
只读数据段:存储常量数据,程序运行过程中不可修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值