1.柔性数组
1.1柔性数组的定义
柔性数组是指在结构体中定义的,其大小在编译时未确定,而在运行时动态分配的数组。这种数组允许结构体的大小根据需要动态变化。语法如下:
struct D
{
int a;
int arry1[0];
};
struct F
{
int a;
int arry2[];
};
柔性数组有上述两种写法,具体实现依据编译器,vs编译器都支持
1.2柔性数组的特点
(1)结构体中,在柔性数组成员之前至少还有一个成员
(2)柔性数组属于结构体的最后一个成员
(3)sizeof计算的结构体大小不包括柔性数组的大小
(4)包含柔性数组的结构体使用malloc分配的内存需要大于结构体的大小,以适应柔性数组的预期大小
1.3柔性数组的使用
#include <stdio.h>
#include <stdlib.h>
struct D
{
int a;
int arry1[0];
};
int main()
{
struct D * p = (struct D* )malloc(sizeof(struct D) + 10 * sizeof(int));
if (p == NULL)
{
perror("malloc");
return 1;
}
for (int i = 0; i < 10; ++i)
p->arry1[i] = i;
struct D * temp = (struct D*)realloc(p, sizeof(struct D) + 20* sizeof(int));
if (temp != NULL)
p = temp;
for (int i = 0; i < 20; ++i)
printf("%d ", p->arry1[i]);
free(p);
p = NULL;
return 0;
}
(1)柔性数组之所以有柔性,是因为该数组的大小可以根据需要去改变
即使是变长数组,程序运行之后,大小也会被固定
(2)上述的结构体成员存在于堆区上,也可以通过下面的方式进行实现
先在堆区创建一个包含指针的结构体
再在堆区分配一定大小的内存,用结构体的指针指向这块内存
#include <stdio.h>
#include <stdlib.h>
struct D
{
int a;
int *arry1;
};
int main()
{
struct D* p = (struct D*)malloc(sizeof(struct D));
if (p == NULL)
{
perror("malloc");
return 1;
}
int* temp = (int*)malloc(20 * sizeof(int));
if (temp != NULL)
p->arry1 = temp;
for (int i = 0; i < 20; ++i)
p->arry1[i] = i;
for (int i = 0; i < 20; ++i)
printf("%d ", p->arry1[i]);
free(p->arry1);
p-> arry1 = NULL:
free(p);
p = NULL;
return 0;
}
1.3.2两种方法的总结
(1)第一种方法是
在堆区开辟一块连续的内存,使用一次malloc和free即可
struct D
{
int a;
int arry[0];
};
(2)第二种方法不一定连续,需要使用两次malloc和free
struct D
{
int a;
int *arry;
};
相比之下,方法1具有两个好处:
(1)方便内存释放:一次free即可
(2)有利于访问速度:连续的内存访问速度更快
2.c/c++程序中内存区域的划分
主要针对,学习程序语言时的划分
图片来源:鹏哥c语言
(1)栈区(stack):主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等
特点:
1.内存分配和释放速度快
2.大小有限,较大的局部变量或深度递归可能导致栈溢出
3.在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时 这些存储单元⾃动被释放
(2)堆区(heap):用于动态内存分配
特点:
1.由程序员手动分配和释放(使用malloc
、new
等函数,以及free
、delete
等函数)
2.如果程序员不释放内存,则可能会导致内存泄漏
3.堆区的大小受限于计算机系统中有效的虚拟内存,相对灵活且较大
(3)数据段(静态区):用于存储全局变量和静态变量。
特点:
1.数据段在程序编译时已经分配了内存并初始化了初始值
2.未初始化的全局变量和静态变量在程序开始执行时会被自动初始化为零(对于数值类型变量)
3.通常包括全局变量、静态变量以及字符串常量(尽管字符串常量本身可能存储在只读区域,但其引用或指针可能存储在数据段中)
(4)代码段:用于存储程序的机器指令