-seventy-
Welcome to my blog space.

内存区域划分

/*
内存区域的划分
四个:常量区,栈区,堆区,静态全局区
五个:常量区,栈区,堆区,静态全局区,代码区

1.代码区:存代码
2.常量区:存常量
3.静态全局区:静态(static)变量,全局变量
4.栈区:普通局部变量
5.堆区:由程序员手动申请,手动释放
*/

# include <stdio.h>

int a;                // 普通“全局”变量(初识值默认为零)
// 作用域:当前项目
// 生命周期:程序开始到结束

static int b;        // 静态“全局”变量(初识值默认为零)
// 作用域:当前文件
// 生命周期:程序开始到结束

int main()
{    
    int c;            // 普通局部变量(无初始值)
    // 作用域:当前语块
    // 生命周期:当前语块

    static int d;    // “静态”局部变量(初识值默认为零)
    // 作用域:当前语块
    // 生命周期:程序开始到结束

    return 0;
} 
# include <stdio.h>

void func()
{
    static int num;        // 只会定义一次

    printf("%d \n", num);
    num++;
    printf("%d \n", num);

}

int main()
{    
    func();
    func();
    func();

    return 0;
} 

/*
    运行结果:
        0
        1
        1
        2
        2
        3
        请按任意键继续. . .
*/

空类型指针

/*
    void* 指针
    1.不能自增自减
    2.不能偏移
    3.不能读取内容
    但是!可以接收任何类型的指针而不需要强转类型
    可以利用这个特点,将 void* 指针当作通用的存放地址的“容器”
    e.g.
        int a = 6,b = 8.8;

        int* p1 = &a;
        double* p2 = &b;

        void* p0 = NULL;    // 当作存放“内存地址”的容器使用
        p0 = p1;
        p0 = p2;
        ...

*/

# include <stdio.h>

int main()
{    
    void* p0 = NULL;

    return 0;
} 

简单开辟内存

/*
    简单开辟内存
        1.申请
        ---有两个函数能够实现申请内存的功能:
            A. malloc(参数:需要字节的总数);
            B. calloc(参数:每个需要的字节数,个数);
            返回值都是 void* 类型的指针
        2.使用
        3.释放
            free(参数:首地址)
            如果不释放的话,会导致“内存泄露”
        4.置空
            如果不置空的话,会出现“野指针”
*/

# include <stdio.h>

int main()
{    
    /* malloc */
    double* p = (double*)malloc(sizeof(double));    // 申请一个double类型大小的内存(8字节)
    *p = 3.14;    // 使用
    printf("%lf \n", *p);
    free(p);    // 通过 p 里面存储的首地址,找到相对应的内存,从这里开始释放,一直释放到,申请内存的时候,做了标记的地方
    p = NULL;    // 通过置空,让指针不再指向已经被释放掉的内存


    /* calloc */
    float* p1 = (float*)calloc(sizeof(float),1);
    *p1 = 3.14f;
    printf("%f \n", *p1);
    free(p1);
    p1 = NULL;


    printf("进阶运用 \n");


    // 进阶运用
    p = (double*)malloc(sizeof(double)*10);    // 申请10个 double 类型大小的连续的内存(补充:因为上面将p定为 double* 而且置空过了,所以可再度利用)
    for (int i = 0; i < 10; i++ )
    {    
        *(p + i) = 10 + i;    // 给值
        printf("%lf \n", *(p + i));    // 展示值
    }
    free(p);
    p = NULL;
    /*
        对于上面 for 循环部分的补充:
        p:里面存的是:申请的内存的首地址
        在一次申请中,申请的内存是连续的
        *(p + i) <===> p[i]        // 注意!它不是数组!
    */
    
    return 0;
} 
# include <stdio.h>

int main()
{    
    // 指针布局
    int row = 3;
    int** pp = (int**)calloc(sizeof(int*), row);

    int len = 4;
    for (size_t i = 0; i < row; i++)    // size_t是什么?点我跳转学习
    {
        pp[i] = (int*)calloc(sizeof(int), len);
    }

    // 内容展示
    for (size_t i = 0; i < row; i++)
    {
        for (size_t j = 0; j < len; j++)
        {    
            pp[i][j] = i * 10 + j;    // 给值
            printf("%-5d", pp[i][j]);    // 展示值,注意!这里不是二维数组!(看不懂请回顾上页内容)
        }
        printf("\n");
    }

    // 释放内存
    for (size_t i = 0; i < row; i++)
    {
        free(pp[i]);
        pp[i] = NULL;
    }
    free(pp);
    pp = NULL;
    
    
    return 0;
} 

自动扩容

# include <stdio.h>

int main()
{    
    int len = 5;    // 默认长度
    int* p = (int*)calloc(sizeof(int), len);
    
    int num = 1;
    for (size_t i = 0; num != 0; i++)    // 用户不输入0结束,就一直获取数据并复制到开辟的内存中
    {
        scanf("%d", &num);
        p[i] = num;        // 数据复制到开辟的内存中
    }
    for (size_t i = 0; p[i] != 0; i++)
    {
        printf("%-5d", p[i]);    // 展示数据
    }
    free(p);
    p = NULL;
    
    return 0;
} 
/*
    扩容的本质是:
        将小内存中的所有内容拷贝到大内存中,然后,再继续对大内存进行别的操作
*/

# include <stdio.h>

int main()
{    
    // 长度
    int len = 5;
    // 首次申请内存
    int* p = (int*)calloc(sizeof(int), len);
    int* temp = p;    // 成为p的分身,以防万一

    // 重复输入数据(并复制到内存中)
    int num = 1;
    int i = 0;
    while (scanf("%d", &num), num != 0)
    {
        if (i < len)    // 没满的情况下
        {
            temp[i++] = num;    // 存完一次,记录一下
        }
        else   // 满了的情况下
        {
            len += 5;
            p = (int*)calloc(sizeof(int), len);        // 重新申请更大的内存
            for (int j = 0; j < i; j++)
            {
                p[j] = temp[j];
            }
            free(temp);
            temp = NULL;
            temp = p;    // 继续成为当前p的分身
            temp[i++] = num;
        }
        
    }
    // 输出数据
    printf("--------------------\n");
    for (int j = 0; j != i; j++)
    {
        printf("%d \n", temp[j]);
    }

    free(p);
    p = NULL;
    temp = NULL;
    
    return 0;
} 

 

posted on 2023-07-14 15:11  -seventy-  阅读(12)  评论(0)    收藏  举报