C语言中,内存分配是程序管理内存资源的关键部分。它分为两种主要类型:静态内存分配和动态内存分配。动态内存分配可以根据程序运行时的需要动态分配和释放内存。动态内存分配由于在编译时分配内存,因此速度很快。编译器自动管理内存的分配和释放。

1、静态内存分配

静态内存分配是在编译时完成的,内存的分配不会在程序运行时改变。变量在程序整个运行周期内都存在,通常是全局变量或局部静态变量。这种方式的内存分配由编译器自动管理,程序员不需要手动控制。

1)全局变量

在函数外部定义,可以在程序的任何部分被访问。

#include <stdio.h>

// 全局变量
int counter = 0;

void increment() {
    counter++;  // 直接访问全局变量
}

int main() {
    printf("初始值:%d\n", counter);
    increment();
    printf("增加后:%d\n", counter);
    return 0;
}

2)局部静态变量

在函数内部定义,使用static关键字,虽然作用域局限于该函数,但其值在函数调用之间持续存在。

#include <stdio.h>

void function() {
    // 静态局部变量
    static int num = 0;
    num++;
    printf("当前值:%d\n", num);
}

int main() {
    function();  // 第一次调用:1
    function();  // 第二次调用:2
    function();  // 第三次调用:3
    return 0;
}

2、动态内存分配

动态内存分配是在程序运行时进行的,可以根据需要动态地分配和释放内存。在C语言中,动态内存分配通常通过以下几个标准库函数实现:

1)malloc(size_t size)

分配size字节的内存块,并返回一个指向它的指针。分配的内存块未初始化。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int n = 5; // 假设我们想创建一个包含5个整数的数组
    int *arr = (int*) malloc(n * sizeof(int)); // 动态分配内存

    if (arr == NULL) {
        printf("Memory allocation failed\n");
        return 1; // 如果内存分配失败,退出程序
    }

    // 初始化数组
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1; // 赋值为1, 2, 3, 4, 5
    }

    // 打印数组元素
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr); // 释放内存
    return 0;
}

2)calloc(size_t num, size_t size)

分配足够空间以容纳num个大小为size的元素,返回一个指向它的指针,并将所有位设置为0

#include <stdio.h>
#include <stdlib.h> // 包含对 calloc 的定义

int main() {
    int numElements = 5; // 假设我们需要一个有 5 个元素的数组
    // 为 int 类型的数组分配内存
    int *arr = (int *)calloc(numElements, sizeof(int)); 

    if (arr == NULL) {
        fprintf(stderr, "Memory allocation failed!\n");
        return 1; // 如果内存分配失败,返回错误代码
    }

    // 输出数组的元素,查看它们是否都初始化为 0
    printf("The array elements are:\n");
    for (int i = 0; i < numElements; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 使用完毕后释放内存
    free(arr);

    return 0;
}

3)realloc(void *ptr, size_t size)

调整之前由malloccalloc分配的内存块ptr的大小。如果新大小大于原大小,可能会移动内存块。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int* arr = malloc(10 * sizeof(int)); // 初始分配10个整数的空间
    if (arr == NULL) {
        perror("Initial malloc failed");
        exit(1);
    }

    // 使用arr...

    // 重新分配为更大的内存空间
    int* temp = realloc(arr, 20 * sizeof(int));
    if (temp == NULL) {
        perror("Realloc failed");
        free(arr); // 重要:失败时,原始内存仍需手动释放
        exit(1);
    }
    arr = temp; // 更新arr指针

    // 使用扩展的arr...

    free(arr); // 释放内存
    return 0;
}

3、区别对比

特性

静态内存分配 (int arr[100];)

动态内存分配 (malloc() 等)

分配时机

编译时

运行时

内存位置

栈(stack)或数据段

堆(heap)

大小是否可变

❌ 固定

✅ 运行时可变

速度

较慢(涉及堆管理)

释放方式

自动释放

需要手动 free()

风险

栈溢出(大数组)

内存泄漏或野指针

适合场景

小数组、已知大小的变量

大数据、需要动态控制大小时

4、使用场景

场景

推荐方式

图像处理,图片大小运行时决定

动态内存分配(malloc)

存储 10 个固定整数

静态内存分配

长时间存在的链表/树结构

动态内存分配

临时变量或递归函数局部数组

静态内存(栈上)

推荐文档