- int val = 20;//在栈空间上开辟四个字节
- char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
- void* malloc (size_t size);
- int* p = (int*)malloc(40);
- #include
- #include
- #include
- #include
-
- int main()
- {
- //向内存申请10个整形的空间
- int* p = (int*)malloc(40);
- if (p == NULL)
- {
- //打印错误原因的一个方式
- printf("%s\n", strerror(errno));
- }
- else
- {
- //正常使用空间
- int i = 0;
- for (i = 0; i < 10; i++)
- {
- *(p + i) = i;
- }
- for (i = 0; i < 10; i++)
- {
- printf("%d ", *(p + i));
- }
- }
- //当动态申请的空间不再使用的时候
- //就应该还给操作系统
- free(p);
- //上面是将p断开,但是实际上p还是存储内容,所以我们手动设置为null
- p = NULL;
-
- return 0;
- }
是用来做动态内存的释放和回收的
注意点:free(str)后,实际上str还执行一个空的地址,所以此时str!=NULL
void free (void* ptr);
calloc 函数也用来动态内存分配。可以初始化空间。
- void* calloc (size_t num, size_t size);
- int*p = (int*)calloc(10, sizeof(int));
- int main()
- {
- //malloc(10*sizeof(int))
- int*p = (int*)calloc(10, sizeof(int));
-
- if (p == NULL)
- {
- printf("%s\n", strerror(errno));
- }
- else
- {
- int i = 0;
- for (i = 0; i < 10; i++)
- {
- printf("%d ", *(p + i));
- }
- }
- //释放空间
- //free函数是用来释放动态开辟的空间的
- free(p);
- p = NULL;
-
- return 0;
- }
当初始申请空间不够,这时使用realloc开辟新的空间【调整动态开辟内存空间的大小】
1. 如果p指向的空间之后有足够的内存空间可以追加,则直接追加,后返回p
2. 如果p指向的空间之后没有足够的内存空间可以追加,则realloc函数会重新找一个新的内存区域
开辟一块满足需求的空间,并且把原来内存中的数据拷贝回来,释放旧的内存空间
最后返回新开辟的内存空间地址
3. 得用一个新的变量来接受realloc函数的返回值
void* realloc (void* ptr, size_t size);
- #include
- int main()
- {
- int *ptr = (int*)malloc(100);
- if(ptr != NULL)
- {
- //业务处理
- }
- else
- {
- exit(EXIT_FAILURE);
- }
- //扩展容量
- //代码1
- ptr = (int*)realloc(ptr, 1000);//这样可以吗?(如果申请失败会如何?)
-
- //代码2
- int*p = NULL;
- p = realloc(ptr, 1000);
- if(p != NULL)
- {
- ptr = p;
- }
- //业务处理
- free(ptr);
- return 0;
- }
- //1. 对NULL进行解引用操作
- int *p = (int*)malloc(40);
- //万一malloc失败了,p就被赋值为NULL
- //所以我们在申请完一块空间之后,一定要进行判空操作
- *p = 0;//err
-
- int i = 0;
- for (i = 0; i < 10; i++)
- {
- *(p + i) = i;//err
- }
- free(p);
- p = NULL;
- //2. 对动态开辟的内存的越界访问
- int *p = (int*)malloc(5 * sizeof(int));
- if (p == NULL)
- {
- return 0;
- }
- else
- {
- int i = 0;
- for (i = 0; i < 10; i++)
- {
- *(p + i) = i;
- }
- }
- //
- free(p);
- p = NULL;
- //栈区开辟出来的,不是动态开辟
- int a = 10;
- int* p = &a;
- *p = 20;
- //3. 对非动态开辟内存的free
- free(p);
- p = NULL;
-
- return 0;
- int*p = (int*)malloc(40);
- if (p == NULL)
- {
- return 0;
- }
- int i = 0;
- for (i = 0; i < 5; i++)
- {
- *p++ = i;
- }
- //回收空间
- // 使用free释放动态开辟内存的一部分
- free(p);
- p =NULL;
- int *p = (int*)malloc(40);
- if (p == NULL)
- {
- return 0;
- }
- //使用
- //释放
- free(p);
- //将p设置为空指针,可以防止重复释放产生的错误
- p = NULL;
- while (1)
- {
- malloc(1);
- }
- //面试1:
- void GetMemory(char *p)
- {
- p = (char *)malloc(100);
- }
-
- void Test(void)
- {
- char *str = NULL;
- GetMemory(str);
- strcpy(str, "hello world");
- printf(str);
- }
-
- int main()
- {
- Test();
-
- char*str = "abcdef";
- printf("%s\n", str);
- printf(str);
- printf("abcdef");
-
- return 0;
- }
- void GetMemory(char **p)//**p:是p的地址
- {
- //*p:是p的内容
- *p = (char *)malloc(100);
- }
-
- void Test(void)
- {
- char *str = NULL;
- GetMemory(&str);//传地址
- strcpy(str, "hello world");
- printf(str);
-
- free(str);
- str = NULL;
- }
-
- int main()
- {
- Test();
- return 0;
- }
- char* GetMemory(char *p)
- {
- p = (char *)malloc(100);
- //将p传递除去
- return p;
- }
-
- void Test(void)
- {
- char *str = NULL;
- str = GetMemory(str);
- strcpy(str, "hello world");
- printf(str);
- free(str);
- str = NULL;
- }
-
- int main()
- {
- Test();
- return 0;
- }
- //面试2
- char *GetMemory(void)
- {
- char p[] = "hello world";//局部变量
- //跳出此函数,则p被销毁
- return p;
- }
-
- void Test(void)
- {
- char *str = NULL;
- str = GetMemory();//此时str的p的地址
- printf(str);//非法地址访问,故输出随机值
- }
-
- int main()
- {
- Test();
- return 0;
- }
- //在静态区,出了函数还是可以继续使用
- int* test()
- {
- //使用static,将a放入静态区,出了这个函数,内存并没有被销毁,故在外面还可以访问到
- static int a = 10;//静态区
- int a = 10;//栈区
- return &a;
- }
-
- int main()
- {
- int*p = test();//此时p接收到a的地址
- *p = 20;//将a修改为20
- return 0;//20
- }
- //在堆区,出函数还是存在
- int* test()
- {
- int *ptr = malloc(100);//堆区
- return ptr;
- }
-
- int main()
- {
- int *p = test();
-
- return 0;
- }
- void GetMemory(char **p, int num)
- {
- *p = (char *)malloc(num);//给p创建100个新的char
- }
- void Test(void)
- {
- char *str = NULL;
- GetMemory(&str, 100);
- strcpy(str, "hello");//可以输出
- printf(str);
- //改:忘记free内容,导致内存泄露
- free(str);
- str = NULL;
- }
- void Test(void)
- {
- char *str = (char *)malloc(100);
- strcpy(str, "hello");
- free(str);
- //free了但是没有把指针置为null
- //此处的问题:已经释放的空间,还被使用
- if (str != NULL)//则此时str还不为NUll,则进入判断
- {
- strcpy(str, "world");
- printf(str);
- }
- }
-
- int main()
- {
- Test();//world
-
- return 0;
- }
- void Test(void)
- {
- char* str = (char*)malloc(100);
- strcpy(str, "hello");
- free(str);
- //解决:将str置为NULL
- str = NULL;
- if (str != NULL)
- {
- strcpy(str, "world");
- printf(str);
- }
- }
-
- int main()
- {
- Test();//world
-
- return 0;
- }
1. 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结 束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是 分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返 回地址等。
2. 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分 配方式类似于链表。
3. 数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。
4. 代码段:存放函数体(类成员函数和全局函数)的二进制代码。
结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。
- struct S
- {
- int n;
- int arr[10];
- };
-
- struct S
- {
- int n;
- int arr[];//未知大小的
- };
-
- struct S
- {
- int n;
- int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
- };
- 结构中的柔性数组成员前面必须至少一个其他成员。
- sizeof 返回的这种结构大小不包括柔性数组的内存。
- 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大 小,以适应柔性数组的预期大小。
- //代码1
- int i = 0;
- type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
- //业务处理
- p->i = 100;
- for(i=0; i<100; i++)
- {
- p->a[i] = i;
- }
- free(p);
- struct S
- {
- int n;
- int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
- };
-
- int main()
- {
- struct S s;
- printf("%d\n", sizeof(s));//
- //sizeof(struct S):不包括int arr的大小
- //5*sizeof(int):手动的给arr赋值
- struct S* ps = (struct S*)malloc(sizeof(struct S)+5*sizeof(int));
- ps->n = 100;
-
- int i = 0;
- for (i = 0; i < 5; i++)
- {
- ps->arr[i] = i;//0 1 2 3 4
- }
- //开辟内存
- struct S* ptr = realloc(ps, 44);
- if (ptr != NULL)
- {
- ps = ptr;
- }
- for (i = 5; i < 10; i++)
- {
- ps->arr[i] = i;
- }
- //打印arr所有数值
- for (i = 0; i < 10; i++)
- {
- printf("%d ", ps->arr[i]);
- }
-
- //释放
- free(ps);
- ps = NULL;
-
- return 0;
- }
- struct S
- {
- int n;
- int* arr;
- };
- int main()
- {
- //sizeof(struct S):此时包括int* arr
- struct S* ps = (struct S*)malloc(sizeof(struct S));
- //再一次给arr创建动态内存
- ps->arr = malloc(5 * sizeof(int));
-
- int i = 0;
- for (i = 0; i < 5; i++)
- {
- ps->arr[i] = i;
- }
- for (i = 0; i < 5; i++)
- {
- printf("%d ", ps->arr[i]);
- }
- //调整大小
- int* ptr = realloc(ps->arr, 10 * sizeof(int));
- if (ptr != NULL)
- {
- ps->arr = ptr;
- }
- for (i = 5; i < 10; i++)
- {
- ps->arr[i] = i;
- }
- for (i = 0; i < 10; i++)
- {
- printf("%d ", ps->arr[i]);
- }
- //释放内存:注意释放顺序
- free(ps->arr);
- ps->arr = NULL;
- free(ps);
- ps = NULL;
-
- return 0;
- }
上述 代码1 和 代码2 可以完成同样的功能,但是 方法1 的实现有两个好处: