[TwistedFate]程序存储区划分、动态申请内存、内存操作函数

内存区划分

内存区划分为5个区:栈区 堆区(程序员管理) 静态区 常量区 代码区
内存地址: 内存地址大 ———-> 内存地址小

代码区

    电脑的存储都是以二进制数据存储的
    书写的代码 会被系统转化为二进制数据 存储在代码区

常量区

    常量区存储常量的特点:
    常量是程序运行期间 不能改变量
    char *str =":";
    // 把h更改成w
    // *(str + 1) = 'w'; // 运行崩溃
    // 指针的赋值是指针的重指向(没有改变常量的值)
    str = "haha";
    char str[] = "zhuang";
    // 数组名字 地址 数组首元素的地址
    // 数组首元素的常量地址
    // 把h 更改成 w
    // 是把常量区的常量字符串拷贝到栈区
    str[1] = 'w';
    // str = "haha" 错误 不能更改

静态区

静态区存储两种变量
(1)静态变量:
    利用关键字 static 修饰的变量 叫做静态变量 并且存储在静态区 
    `static int number1;`
    特点:1.如果初始化不赋值,默认是0;
             2.只初始化一次
    举例比较:
    void function()
    {
        static int num = 10;
        num++
        printf("%d ",num);
    }
    // 输出三次结果为:11 12 13
    void function1()
    int num1 = 10;
    num1++;
    printf("%d ",num1);
    // 输出结果三次为:11 11 11 
(2)全局变量

静态区变量 保存周期:直到你的程序运行结束,静态变量才会被释放

栈区

栈区大概7M - 8M
出栈与入栈的规则:先入栈——>栈底, 再出栈
入栈:又称压栈
之所以栈区 容量不是特别大又不会出现崩溃的现象 是因为 栈区频繁的进行出栈入栈 只要一次性不把栈空间堆满 不会轻易的出现崩溃
注意:定义变量的时候 切记给初值 避免出现莫名其妙的问题

堆区

堆区 是程序员开辟空间 是程序员释放空间
手动开辟空间 手动释放空间
堆区的空间 大概就是全部存储空间

开辟空间函数

void *malloc(字节大小)
void * 表示无类型指针 开辟了四个字节的堆内存空间
    // 给整型指针p指向的位置 开辟了四个字节的堆内存空间
    int *p = malloc(4);
    *p = 10;
    printf("%d \n",*p);

    char *str = malloc(8);
    strcpy(str, "wang");    // 正确
    stpcpy(str, "wangwangwang");  //错误的,开辟了多少空间 不要超过开辟的空间
    printf("%s\n",str);
    int *p1 = malloc(4);
    *p1 = 5;
    short *p2 = malloc(4);  // 开辟多少空间 最好用多少
    *p2 = 10;
    *(p2 + 1) = 15;

释放空间函数

free(void *)
1.标记删除 不会抹去该空间存储的数据 只会把这块空间标记为可用
2.把指针置空
    // 开辟空间
    int *p = malloc(4);
    // 使用空间
    *p = 10;
    printf("%d\n",*p);
    // 释放空间
    free(p);
    p = NULL;
// 改错
int *p = malloc(sizeof(int) * 5);
for(int i = 0;i < 5;i++)
{
    *p = i + 1;
    p++;
}
free(p);
// 指针发生了变化 释放了本不属于你的开辟区域 就会崩溃
// 修改 把指针改回去
free(p - 5);
p = NULL;

/** 练习
* 有⼀字符串,其中包含数字,提取其中的数字.要求动态分配内存保存
提⽰: 先计算出有⼏个数字,然后根据数字的个数来开辟空间
*/

char str[] = "dsad123dsa23";
int count = 0;
for(int i = 0;i < strlen(str);i++)
{
    if(str[i] >= '0' && str[i] <= '9' )
    {
        count++;
    }
}
// 开辟空间
char *strValue = malloc(count + 1); //加1是因为字符串有个'\0'
// 记录数字该放的位置
int index = 0;
for(int i = 0; i < strlen(str);i++)
{
    if(str[i] >= '0' && str[i] <= '9')
    {
        strValue[idnex] = str[i];
        index++;
    }
}
// 加上'\0'
strValue[index] = '\0';
printf("%s",strValue);
// 释放空间
free(strValue);
strValue = NULL;

/** 练习2:
* 输⼊3个学员的姓名,动态分配内存保存学员姓名,并在最后输出
*/

    char *word[3] = {0};
    char str[] = {0};
    for(int i = 0;i < 3;i++)
    {
        printf("请输入一个字符:\n");
        scanf("%s",str);
        // 开辟空间
        words[i] = malloc(strlen(str) + 1);        
        // 保存字符串
        strcpy(words[i], str);
    }
     for (int i = 0; i < 3; i++) {
     printf("%s\n",words[i]);
     // 释放空间
     free(words[i]);
     words[i] = NULL;
    }

其他分配函数

在堆内存中 开辟 n * size 个空间 并且把开辟的空间清零 因为有一个清零的过程 所以效率偏低
// calloc(int n, size)

 int *p = calloc(3, sizeof(int));
 free(p);
 p = NULL;

重新分配函数 realloc
realloc(原分配地址,新空间大小)
两种情况:
情况1:如果原来分配的地址 可以扩充空间 那么就在原来的地址扩充
情况2:如果原来分配的地址 不能扩充了 那么系统会重新分配一个空间 并且把原来的地址存储的数据拷贝到新空间 然后系统自动释放原地址的空间

    int *p_old = malloc(10);
    int *p_new = realloc(p_old, 25);
    printf("%p %p\n",p_old,p_new);
    // free(p_old);     // 过度释放
    free(p_new);
    p_new = NULL;

内存操作函数

// 把开辟的空间 多少字节 重置成 c
// memset(开辟的空间的指针, int c, 字节)
// 用途:把开辟好的空间 清零

int *p = malloc(sizeof(int) * 4);
for (int i = 0; i < 4; i++) {
    p[i] = i + 5;
}
// 清零
memset(p, 0, 16);
for (int i = 0; i < 4; i++) {
    printf("%d ",p[i]);
}

// 从来源拷贝到目的地 多少个字节
// memcpy(目的地,来源 , 字节数)
char str1[] = “wanglong”;
char str2[] = “44”;
memcpy(str1, “W”,1);
memcpy(str1 + 3, str2, 2);
printf(“%s”,str1);

// 比较函数
// 两个地址 按字节 进行比较返回第一个不同的差值
// memcmp(指针1, 指针2, 字节数)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值