当前位置 : 主页 > 编程语言 > c语言 >

【柔性数组与局部性原理】

来源:互联网 收集:自由互联 发布时间:2023-09-03
柔性数组概念 柔性数组特点 局部性原理 柔性数组概念对于柔性数组,也许你之前从未听说过,柔性数组,顾名思义,就是数组,它的柔性柔在元素个数可以动态变化,即柔性数组是未

柔性数组概念

  • 柔性数组特点
  • 局部性原理

柔性数组概念 对于柔性数组,也许你之前从未听说过,柔性数组,顾名思义,就是数组,它的柔性柔在元素个数可以动态变化, 即柔性数组是未知大小的,数组大小可以动态变化的。 在结构体中,最后一个元素允许是未知大小的数组,这个数组就叫柔性数组成员。下面直接举例子来说明柔性数组。struct S { int n; int arr[]; };这就是一个柔性数组,柔性数组是在结构体中是未知大小的。struct S { int n; int arr[0]; };上面这种写法也可以。 当我们进行编译时,编译通过。

柔性数组特点: 下面举例说明柔性数组的特点:假设需要动态开辟一块内存空间,我们可以这样操作:typedef struct S { int n; int arr[]; };当我们计算这个柔性数组的大小时,结果如下: 看到结果是4,可能你会疑惑,别着急,这就是柔性数组的第一个特点:特点1:sizeof计算结构体大小时,不包括柔性数组的大小所以计算上面的结构体的大小时,仅计算n大小,在进行结构体内存对齐后,结果是4 。特点2:柔性数组成员之前必须至少有一个其他成员。特点3:包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。什么意思呢?举个例子:typedef struct S { int n; int arr[0]; }S; int main() { struct S s = { 0 }; struct S* ps = (S*)malloc(sizeof(S) + 5 * sizeof(int)); return 0; }看上面的代码:当我们动态申请一块内存时,申请的空间需要大于结构体本身的大小。 在后面增加适当的空间以适应柔性数组的大小。下面举实际例子来说明柔性数组的一些好处:typedef struct S { int n; int arr[0]; }S; int main() { struct S s = { 0 }; struct S* ps = (S*)malloc(sizeof(S) + 5 * sizeof(int)); if (ps == NULL) { printf("%s\n", strerror(errno)); return; } ps->n = 100; int i = 0; for (i = 0; i < 5; i++) { ps->arr[i] = i; } }在内存中申请一块空间,这块空间在内存中是连续的。 然后将n 和arr分别赋值 如果想使用的空间不够,那就重新申请空间struct S*ptr=realloc(ps, 44);44 = 24(原结构体大小) + 20(5*int)也就是再开辟五个int类型的空间int main() { struct S s = { 0 }; struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int)); if (ps == NULL) { printf("%s\n", strerror(errno)); return; } ps->n = 100; int i = 0; for (i = 0; i < 5; i++) { ps->arr[i] = i; } struct S*ptr=realloc(ps, 44); if (ptr != NULL) { ps = ptr; } for (i = 5; i < 10; i++) { ps->arr[i] = i; } 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() { struct S* ps = (struct S*)malloc(sizeof(struct S)); ps->arr = malloc(sizeof(int) * 5); int i = 0; for (i = 0; i < 5; i++) { ps->arr[i] = 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);//free要有先后顺序 free(ps); ps = NULL; return 0; }看不懂代码?请看下图: 首先申请了第一块空间结构体指针ps,该指针指向了上面的S结构体,第二次申请的空间是 ps所指向的结构体成员指针arr,为这个arr成员申请了一块空间,然后增加空间。在两次申请的过程中,两块空间ps 和 arr所指向的空间 都是在堆区上,结构体是在栈区上,所以释放的时候,只释放申请出来的两块空间,不需要释放结构体空间。对比两段代码,可以看出不同点:在第一段代码中,申请的空间是连续的,第二段代码中,申请的空间是不连续的。第一段代码申请的空间只需free一次,第二段代码申请的空间需要free两次,并且free的先后顺序有要求,需要先释放arr指向的空间,再释放ps。如果释放顺序相反,会导致arr指向的空间就失踪了, 也就是没人能知道arr指向的空间在哪。所以,在这里使用柔性数组的好处有:1.方便释放空间。2.利于内存访问第二点如何理解?下面引出局部性原理的概念:

局部性原理 局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中。意思是:当我们访问一块空间时,接下来有 80%的可能性会访问它周边的数据。来看下面:一个存储器层次结构图如上:直接画出主要的布局: cpu在访问空间时,首先会在寄存器中读取数据,如果寄存器中没有那块需要读取的空间,就会去高速缓存中寻找,如果高速缓存中也没有这块内存区域,它就会去硬盘中寻找。这样层层往下寻找。 如上图: 假如需要读取的空间是连续的,那么这块空间放在寄存器中时,cpu先读取一小部分空间,根据局部性原理:cpu有80%的几率读取周围的空间,这样就能够提高访问效率。 这就是使用柔性数组的好处假如读取的空间是不连续的,而是碎片式的访问。这样读取效率就会降低。 所以,柔性数组的好处在于: 1.方便释放空间。2.利于内存访问

上一篇:gdb 速记
下一篇:没有了
网友评论