C语言讲义——内存管理
动态分配内存
动态分配内存,在堆(heap)中分配。
void *malloc(unsigned int num_bytes);
- 头文件 stdlib.h或malloc.h
- 向系统申请分配size个字节的内存空间
- 返回void* 类型(未确定类型的指针)
- 可强制转换为任何类型的指针
void *memset(void *s,int c,size_t n)
- 头文件 string.h或memory.h
- 将内存空间s的前n个字节的值设为值c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void getResult(char *pp) {
pp = (char *)malloc(10);
memset(pp, 0, 10);
strcpy(pp, "函数内");
}
void testMalloc() {
char *p = NULL;
getResult(p);
printf("getResult()后:%s\n", p);
p = (char *)malloc(10);
memset(p, 0, 10);
strcpy(p, "调用方");
printf("%s\n", p);
}
int main(int argc, char *argv[]) {
testMalloc();
return 0;
}
二级指针
二级指针——指向指针的指针
如果要在函数中申请内存,调用放还想得到申请的新内存的话,需要使用二级指针:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int g_size = 20;
//申请新的内存空间
void _exploit(char **pp) {
*pp = (char *)malloc(g_size);
memset(*pp, 0, g_size);
strcpy(*pp, "函数内的新空间");
}
//释放内存空间
void _giveBack(char **pp) {
if (*pp != NULL) {
free(*pp);
*pp = NULL;
}
}
main() {
char *p = NULL;
_exploit( &p );
printf("【%s】\n", p);
_giveBack(&p);
printf("【%s】\n", p);
p = (char *)malloc(g_size);
memset(p, 0, g_size);
strcpy(p, "调用方的新空间");
printf("【%s】\n", p);
_giveBack(&p);
printf("【%s】\n", p);//不加【】不打印(null),加了才打印
}
lloc系列函数
malloc | 动态分配内存,需要与memset配合使用 |
---|---|
calloc | 动态分配完内存后,自动初始化内存空间为零 |
realloc | 为数组重新分配内存 |
#include<stdio.h>
#include<stdlib.h>
main() {
char *p = NULL;
printf("p:%s\n", p);
p = (char *)malloc(10);
printf("p:%s\n", p);
if (p!=NULL) {
free(p);
p=NULL;
}
p = (char *)calloc(10,sizeof(char));
printf("p:%s\n", p);
if (p!=NULL) {
free(p);
p=NULL;
}
printf("p:%s\n", p);
}
#include <stdio.h>
main() {
char arr[3];
int n = 1;
int i = 1;
printf("n = %d\n", n);
char *p = &arr[0];
char *p2 = realloc(p, 10);
for(i = 0; i<10; i++) {
arr[i] = 9;
}
printf("n = %d\n", n);
}
释放内存
- malloc等内存分配函数开辟的内存来自于堆(heap),
- 堆是有限的,不能只开辟,不释放,
- 使用free函数释放不使用的内存。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void testMalloc() {
char *p = (char *)malloc(10);
memset(p, 0, 10);
strcpy(p, "调用方");
printf("p:%s\n", p);
if(p != NULL) {
free(p);
p = NULL;
}
printf("p:%s\n", p);
}
int main(int argc, char *argv[]) {
testMalloc();
return 0;
}
示例:猜价格
知识点:
- 内存管理
- 二级指针
- 循环
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getResult(int n, char **pp) {
int nRealPrice = 2999;
*pp = (char *)malloc(10);
memset(*pp, 0, 10);
if (n > nRealPrice) {
strcpy(*pp, "高了");
return 0;
} else if (n < nRealPrice) {
strcpy(*pp, "低了");
return 0;
} else {
strcpy(*pp, "正确");
return 1;
}
}
void setFree(char **pp) {
if(*pp != NULL) {
free(*pp);
*pp = NULL;
}
}
void guessPrice() {
int n = 0;
char *p = NULL;
int nRet = 0;
do {
scanf("%d", &n);
nRet = getResult(n, &p);
printf("p:%s\n", p);
setFree(&p);
printf("p:%s\n", p);
} while(nRet == 0 );
}
int main(int argc, char *argv[]) {
guessPrice();
return 0;
}
模拟Java的ArrayList的add()方法
ArrayList又叫动态数组,长度不够的时候可以自动申请新的内存。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int capacity = 3;
static int index = 0;
void foreach(char * p) {
puts("");
for(int i = 0; i<=index; i++) {
printf("%c ", *(p+i));
}
puts("");
}
void add(char **p, char c) {
if (*p == NULL) {
*p = (char*)calloc(capacity, sizeof(char));
} else {
if(index >= capacity ) {
capacity += (capacity>>1);
printf("新容量:%d \n", capacity);
char *p2 = (char*)realloc(*p, capacity);
//free(*p);
*p = p2;
}
}
*(*p+index) = c;
index++;
//printf("index = %d \n",index);
}
main() {
char* p = NULL;
int n = 1000;
for(int i = 0; i<20; i++) {
add(&p, 'A');
foreach(p);
}
printf("int = %d \n", n);
}