C语言内存动态分配函数 | 您所在的位置:网站首页 › c语言calloc和malloc › C语言内存动态分配函数 |
内存动态分配函数
主要涉及malloc/calloc/realloc和free四个函数,头文件:#include (1)malloc函数原型: void *malloc(size_t size); 说明 向系统申请分配一个长度为size大小字节的内存块,并返回内存块的起始地址。 返回值 如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。 演示示例: #include #include int main() { /* 1. malloc返回的是void *类型,在需要时候的时候要做一个适合目标指针类型的转换,比如这里转换成int *; 如果是 char *p_a = (char *)malloc(10); */ int *p_a = (int *)malloc(10 * sizeof(int)); //int *p_a = (int *)malloc((size_t)(1024*1024*1024*2)); //执行此句就会执行失败, //所以malloc之后一定要做一个是否申请内存成功的判断 if (!p_a) { printf("malloc 失败, p_a = %p\n", p_a); exit(1); } // 2.malloc分配的内存它的值是随机 printf("malloc刚申请的一段内存其值是:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } printf("\n"); // 赋初值 for (int i = 0; i < 10; i++) { *(p_a + i) = i; } printf("初始化后的数据:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } printf("\n"); printf("free前的p_a = %p\n", p_a); free(p_a); //p_a = NULL; // 3. 测试free后指向的内存区域数值 printf("free后的p_a = %p\n", p_a); printf("测试free后指向的内存区域数值:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } printf("\n"); /* printf("测试free还往其指向的内存空间写数据:\n"); for (int i = 0; i < 10; i++) { *(p_a + i) = i; //往free后的空间写数据,程序出错 } */ printf("程序结束\n"); return 0; }使用结论: (1)malloc返回的是void *类型,在需要时候的时候要做一个适合目标指针类型的转换, 比如char *p_a = (char *)malloc(10); (2)malloc分配的内存它的值是随机;比如分配的字符串空间char *p_a = (char *)malloc(10),如果我们直接操作strlen(p_a)则结果不确定。可以用memset去赋予初值。 (3)在free后就不要再去操作该段内存区(不管是读还是写)。 (4)malloc后要判断内存是否申请成功。 (2)calloc函数原型: void *calloc(size_t n, size_t size); 返回值 如果分配成功则返回指向被分配内存的指针(此存储区中的初始值已被设置为0),否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。 与malloc的区别 (1)传入参数不一样; 比如申请同样10个int的内存空间 int *p_a = (int *)malloc(10*sizeof(int)); int *p_b = (int *)calloc(10, sizeof(int)); (2)calloc申请的内存是有将其值初始化为0,而malloc则是随机的; 和malloc相同之处 (1)都是要用free去释放申请的内存; (2)该段内存被free后都不要再去操作该段内存(不管读还是写) 什么使用calloc或malloc呢? (1)如果你想把申请的内存区域初始化为0,可以使用calloc; 初始化为0是要花时间的。 (2)如果你的应用在内存申请后会手动赋予值,可以使用malloc。 即使你用了malloc,但是想把数据初始化为0,则用memset去初始化就可以了。 代码演示: #include #include int main() { //int *p_a = (int *)malloc(10*sizeof(int)); // 1. calloc的参数和malloc有区别 int *p_a = (int *)calloc(10, sizeof(int)); if (!p_a) { printf("malloc 失败, p_a = %p\n", p_a); exit(1); } // 2. calloc申请的一段内存空间其值都被初始化为0 printf("calloc刚申请的一段内存其值是:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } printf("\n"); for (int i = 0; i < 10; i++) { *(p_a + i) = i; } printf("初始化后的数据:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } printf("\n"); printf("free前的p_a = %p\n", p_a); free(p_a); //p_a = NULL; // 3. 测试free后指向的内存区域数值 printf("free后的p_a = %p\n", p_a); printf("测试free后指向的内存区域数值:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } return 0; }结果: (3)realloc函数原型 void* realloc(void* ptr, unsigned newsize); 给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度。 返回值 如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。 说明 realloc可以对给定的指针所指的空间进行扩大或者缩小,无论是扩大或是缩小,原有内存的中内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。 realloc并不保证调整后的内存空间和原来的内存空间保持同一内存地址。 比如 相反,realloc返回的指针很可能指向一个新的地址。 图示理解:比如要重新分配已经malloc的内存 代码演示: #include #include int main() { int *p_a = (int *)malloc(10 * sizeof(int)); //申请10*sizeof(int)字节的空间 // 1. 给p_a指向的内存做初始化 for (int i = 0; i < 10; i++) { *(p_a + i) = i; // 赋值 } printf("\n初始化p_a指向内存的数值:\n"); for (int i = 0; i < 10; i++) { printf("%d ", *(p_a + i)); } // 1. 扩充数据,从10个int变为15个int printf("\n扩充之前p_a = %p\n", p_a); p_a = (int *)realloc(p_a, 15 * sizeof(int)); printf("扩充之后p_a = %p\n", p_a); printf("\n扩充之后的的数值:\n"); // 扩充后地址空间是很有可能发生变化的 for (int i = 0; i < 15; i++) { printf("%d ", *(p_a + i)); // 原有的内容的数值没有变化, 但扩充之后的数值是不确定的 } // 2. 缩减数据 p_a = (int *)realloc(p_a, 5 * sizeof(int)); printf("\n缩减之后p_a = %p\n", p_a); printf("\n缩减之后的的数值:\n"); // for (int i = 0; i < 15; i++) { printf("%d ", *(p_a + i)); // 缩减内存后被缩减部分的数据有变化 } // 测试越界使用 for (int i = 0; i < 10; i++) { *(p_a + i) = i; // 赋值 } free(p_a); p_a = NULL; // 内存释放后将p_a置为NULL,这是良好的编程习惯 printf("程序结束\n"); return 0; }结果: 注意: * (1)realloc扩充内存时,原有的数据不变,但扩充的内存的数值是不确定的; * (2)扩展内存后其指针和原来可能不一样; * (3)缩减内存后只能使用其指定长度的数据,不要越界使用。 思考: 使用malloc,memcpy和free去实现一个类似realloc的函数? //待补充 (4)free函数原型: void free(void *ptr) 释放ptr指向的存储空间(ptr指向的内存需要由malloc/calloc或realloc动态申请)。 说明: 在释放内存后,建议将指针置为NULL,这是良好的编程习惯,如 |
CopyRight 2018-2019 实验室设备网 版权所有 |