C语言之动态内存分配二

简介: C语言之动态内存分配二

柔性数组:

C99中,结构中的最后一个元素允许是未知大小的数组,这就叫[柔性数组]成员。

举例:

#include<stdio.h>
struct S
{
  int n;
  int arr[];//未知大小的----柔性数组成员--数组的大小是可以调的
  //注:如果写成arr[]无法通过编译,则可写为arr[0]
};
int main()
{
  struct S s;
  printf("%d\n", sizeof(s));
  return 0;
}

该结构体的大小是不包括柔性数组成员。

4

柔性数组的基本使用:

#include<stdio.h>
#include<stdlib.h>
struct S
{
  int n;
  int arr[];//未知大小的----柔性数组成员--数组的大小是可以调的
  //注:如果写成arr[]无法通过编译,则可写为arr[0]
};
int main()
{
  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
  }
  //使用动态内存开辟的方式,定义柔性数组的大小为20个字节
  struct S*ptr=(struct S*)realloc(ps, 44);
  if (ptr != NULL)
  {
    ps = ptr;
  }
  for (i = 5; i < 10; i++)
  {
    ps->arr[i]=i;//5 6 7 8 9
  }
  for (i = 0; i < 10; i++)
  {
    printf("%d ", ps->arr[i]);
  }
  free(ps);//释放内存
  ps = NULL;
  return 0;
}
0 1 2 3 4 5 6 7 8 9

其他方法实现数组的大小可进行调整:

#include<stdio.h>
#include<stdlib.h>
struct S
{
  int n;
  int* arr;
};
int main()
{
  struct S* ps = (struct S*)malloc(sizeof(struct S));
  ps->arr = (int*)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 = (int*)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]);
  }
  //注:不能先释放ps,因为只有通过ps才能找到realloc调整后的内存
  free(ps->arr);
  ps->arr = NULL;
  free(ps);
  ps = NULL;
  return 0;
}
0 1 2 3 4 0 1 2 3 4 5 6 7 8 9

其分析过程如下:

struct S
{
  int n;
  int* arr;
};

int* ptr = (int*)realloc(ps->arr, 10 * sizeof(int));

int* ptr = (int*)realloc(ps->arr, 10 * sizeof(int));//进行空间调整,假设后面的空间够用,此时直

那么这两种方法那种使用起来更好一些呢?


1:第二种方法中,我们使用了两次malloc,而malloc和free是搭配使用的,那么malloc出现的次数越多,越容易引发错误。


2:malloc在开辟内存空间的时候是只要有空间他就会进行开辟,但其开辟是没有依据的,如下图所示。malloc使用的频率越多,就会导致出现很多的内存碎片,从而大大浪费了内存资源。

3:柔性数组的内存开辟是连续的,而malloc并不是连续的,这样一来malloc开辟的内存在访问的时候效率会大大降低。


柔性数组开辟的内存区域:

malloc开辟的内存区域:


原因:从下往上访问数据的速度越来越快,当寄存器在访问当前数据时,高速缓存器会将当前数据后面的数据传递上去,而如果是malloc开辟的内存空间,他并不是连续的,那么就会导致寄存器找不到我们需要的数据,由此寄存器会在高速缓存器中查找,一直向下查找直到找到为止,这样就大大降低了访问速度,但如果是柔性数组就不会出现这种局部性原理。


柔性数组的特点:

1:结构中的柔性数组成员必须至少包含一个其他成员;

2:sizeof返回的这种结构大小不包括柔性数组的内存。

3:包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。


柔性数组的优势:

一:方便内存释放。

二:有利于访问速度

相关文章
|
27天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
31 3
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
331 0
|
12天前
|
C语言
【c语言】动态内存管理
本文介绍了C语言中的动态内存管理,包括其必要性及相关的四个函数:`malloc`、``calloc``、`realloc`和`free`。`malloc`用于申请内存,`calloc`申请并初始化内存,`realloc`调整内存大小,`free`释放内存。文章还列举了常见的动态内存管理错误,如空指针解引用、越界访问、错误释放等,并提供了示例代码帮助理解。
26 3
|
28天前
|
编译器 程序员 C语言
深入C语言:动态内存管理魔法
深入C语言:动态内存管理魔法
|
1月前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数
|
1月前
|
程序员 C语言
C语言内存函数精讲
C语言内存函数精讲
|
14天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
15 0
|
24天前
|
C语言
保姆级教学 - C语言 之 动态内存管理
保姆级教学 - C语言 之 动态内存管理
16 0
|
28天前
|
存储 C语言
深入C语言内存:数据在内存中的存储
深入C语言内存:数据在内存中的存储
|
28天前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
39 0