内存空间
进程空间图示
image栈内存(Stack)
- 栈中可以存放任意类型的变量, 即自动类型的局部变量, 随用随开,用完即消.
- 栈内存分配从地址大的开始分配
- 栈的内存大小有限, 所以特别在使用递归的时候一定要注意, 栈的溢出问题;
#include <stdio.h>
int main()
{
// 存储在栈中, 内存地址从大到小
int a = 10;
int b = 20;
printf("&a = %p\n", &a); // &a = 0060FEAC
printf("&b = %p\n", &b); // &b = 0060FEA8
return 0;
}
堆内存(Heap)
- 堆内存可以存放任意类型的数据, 但需要自己申请与释放
- 堆大小, 想象中的无穷大, 但实际使用中, 受限于实际内存的大小和内存是否连续性;
#include <stdio.h>
#include <stdlib.h>
int main()
{
// 存储在栈中, 内存地址从小到大
int *p1 = malloc(4);
*p1 = 10;
int *p2 = malloc(4);
*p2 = 20;
printf("p1 = %p\n", p1); // p1 = 00762F48
printf("p2 = %p\n", p2); // p2 = 00762F58
return 0;
}
malloc函数
-
格式: void * malloc(size_t _Size);
-
malloc函数作用: 用于申请堆中的内存的
-
malloc函数开辟好的存储空间,不会进行初始化
-
free函数: 释放我们在堆内存中开辟的一块内存空间
-
memset 函数: 给指定的堆内存进行初始化
-
申请4个字节的存储空间
- (int *)强制类型转换
- malloc函数返回的是void * ,而我们开辟的是4个字节,正好是int类型,
- 所以最好将void *转换为int *,因为只有指针类型是int 类型
- 将来操作这块内存的时候,我们才知道应该操作多少个字节
int *p = (int *)malloc(sizeof(int)); printf("*p = %i\n", *p);
-
小例子
#include <stdio.h>
int main()
{
// 强制类型转换
int *p1 = (int *)malloc(4);
int *p2 = (int *)malloc(sizeof(int));
*p1 = 123;
*p2 = 456;
printf("*p1 = %i\n", *p1);
printf("*p2 = %i\n", *p2);
printf("p1 = %i\n", p1); // 10162952 观察可知,从低地址开始存放
printf("p2 = %i\n", p2); // 10162968
// 通过free函数来手动释放我们申请的空间
free(p1);
free(p2);
// free函数,我们只传递了内存的地址,系统如何知道应该释放多少个字节的存储空间
// 在利用,malloc分配的时候,系统就保存了该指针对应的内存大小;
return 0;
}
-
注意点:
- 使用malloc函数必须导入一个头文件 stdlib.h
- 通过malloc申请的空间默认存储的是垃圾数据, 也就是系统不会帮我们初始化
- 所以一般情况下, malloc都会和memset函数结合起来使用
-
memset作用:
- 格式: memset(void *_Dst, int _Val, size_t _Size)
- 专门用于初始化一块内存空间
- 第一个参数: 传入需要初始化内存的地址
- 第二个参数: 传入需要初始化的值
- 第三个参数: 传入需要初始化的长度
-
memset注意: 使用时必须导入一个头文件string.h
#include <stdio.h>
int main()
{
int *p = (int *)malloc(3 * sizeof(int));
printf("p[0] = %i\n", p[0]); // 垃圾数据
printf("p[1] = %i\n", p[1]); // 垃圾数据
printf("p[2] = %i\n", p[2]); // 垃圾数据
memset(p, 0 , 3*sizeof(int));
for(int i = 0; i < 3; i++){
printf("p[%i] = %i\n", i, p[i]); // 0 0 0
}
return 0;
}
calloc函数
- calloc函数 就是对malloc的封装
- 格式: void *calloc(size_t nmemb, size_t size);
- 第一个参数: size_t nmemb 所需内存单元数量
- 第二个参数: size_t size 内存单元字节数量
- 返回值: void * 成功返回非空指针指向申请的空间 ,失败返回 NULL
int *p = (int *)calloc(3, sizeof(int));
// 告诉操作系统,需要开辟3块存储空间, 每块存储空间占用4个字节
realloc函数
-
例如, 我们利用malloc分配4个字节, 如果4个字节不够用,则想进行扩容,这时候可以使用realloc,反之,缩小也可以
-
注意点:
- 利用malloc函数分配存储空间,必须是连续的,也就是在堆内存中分配内存空间必须是连续的
- 如果利用realloc函数扩容的时候,后面没有连续的内存, 那么系统会分配一块新的内存;
网友评论