动态内存开辟(下)以及柔性数组的介绍

简介: 动态内存开辟(下)以及柔性数组的介绍

一. 几个经典的笔试题


1. 题目一


void Getmem(char* p)
{
  p = (char*)malloc(100);
}
int main()
{
  char* str = NULL;
  Getmem(str);
  strcpy(str, "hello world");
  printf(str);
  return 0;
}


这段代码我们可以发现两个很明显的错误

94ad2782e58749a99b44179f18923a88.png

所以说什么都不会打印


5b07484fa2f34addb2708f42bf13cac4.png


那么 我们要怎么改变才能将它变成对的代码呢


首先 我们可以将str的地址传递进去 使用二级指针来接收 这样指针就能指向开辟内存的那个位置啦


最后 我们记得要回收内存 避免内存泄漏的情况


void Getmem(char** p)
{
  *p = (char*)malloc(100);
}
int main()
{
  char* str = NULL;
  Getmem(&str);
  strcpy(str, "hello world");
  printf(str);
  free(str);
  str = NULL;
  return 0;
}


大家这里要注意的是二级指针的使用


p是一个二级指针 而我们要改变str的地址 我们需要先对p进行解引用来找到str的地址 然后改变它


*p = (char*)malloc(100);
• 1


也就是这一步 要特别注意


我画图来给大家解释一下

f072425c8cfa446bbe624f704dd0a489.png当然这里还有一种方法可以使这个程序运行


代码表示如下


char * Getmem(char* p)
{
  p = (char*)malloc(100);
  return p;
}
int main()
{
  char* str = NULL;
  str =Getmem(str);
  strcpy(str, "hello world");
  printf(str);
  free(str);
  str = NULL;
  return 0;
}


还是画图给大家解释一下


73332b5c48fe4cefbf2bdc37535e780a.png

2. 题目二


char* GetMemory(void) {
  char p[] = "hello world";
  return p;
}
void Test(void) {
  char* str = NULL;
  str = GetMemory();
  printf(str);
}


这里和题目一又有不一样的地方


因为p数组是在栈区上开辟的 离开函数调用完成就自动销毁了


所以说实际上str现在是一个野指针 这个就是一个错误的代码


3. 题目三


void GetMemory(char **p, int num) {
 *p = (char *)malloc(num);
}
void Test(void) {
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);
}


这个代码是可以完美运行的 但是存在一个内存泄漏的问题 只需要在后面释放一下就可以啦


void GetMemory(char** p, int num) {
  *p = (char*)malloc(num);
}
int main() {
  char* str = NULL;
  GetMemory(&str, 100);
  strcpy(str, "hello");
  printf(str);
  free(str);
  str = NULL;
  return 0;
}

802434743df9463e87fcb29748b45587.png


这里看似可以完美运行 实际上str是一个野指针 它指向的内存已经被释放了 所以要注意这点


二. c程序的内存开辟


咱们这里主要主要讨论内存的 栈区 堆区 静态区

6a87271e389c428aa7e01fcbf41518c9.png



三. 柔性数组


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


typedef struct st_type
{
 int i;
 int a[];//柔性数组成员
}type_a;


3.1 柔性数组的特点


1结构中的柔性数组成员前面必须至少一个其他成员。

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

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

小,以适应柔性数组的预期大小。


特点1就是一个结构性的特点 我们注意一下就好


特点2 我们可以来敲代码实验一下


27cd2f0412e34caa8c0381c1c7a76b60.png


3.2 柔性数组的使用

  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);


这里我们使用了动态内存开辟之后 开辟了一个原来结构体(除柔性数组)的大小 外加上一百个int类型数据的大小


然后我们就可以使用数组里的空间啦


此外 我们还有另一个使用方式


int main()
{
  typedef struct st_type
  {
    int i;
    int *pa;//柔性数组成员
  }type_a;
  printf("%d\n", sizeof(type_a));
  int i = 0;
  type_a* p = (type_a*)malloc(sizeof(type_a));
  //业务处理
  p->i = 100;
  p->pa = (int*)malloc(100 * sizeof(int));
  for (i = 0; i < 100; i++) {
    p->pa[i] = i;
  }
  free(p);
  return 0;
}


因为这个时候pa是一个指针 我们可以让它成为一个指针数组


3.3 柔性数组的优势


上面的两种方式能完成同样的功能 但是方式一 也就是柔性数组有两个好处


1 方便内存释放


相比于下面的代码 只需要释放一次内存就够了


2 有利于提高访问速度


连续的内存有利于提高访问速度


这就是我们将柔性数组单独拿出来讲的原因


以上就是本篇博客的全部内容啦 由于博主才疏学浅 所以难免会出现纰漏 希望大佬们看到错误之后能够


不吝赐教 在评论区或者私信指正 博主一定及时修正


那么大家下期再见咯

相关文章
|
8月前
|
编译器 C语言 C++
【C语言】realloc()函数详解(动态内存开辟函数)
【C语言】realloc()函数详解(动态内存开辟函数)
115 0
|
8月前
|
编译器 C++
C/C++动态内存开辟(详解)
C/C++动态内存开辟(详解)
|
7月前
|
C语言
C语言学习记录——动态内存开辟常见的错误
C语言学习记录——动态内存开辟常见的错误
41 1
|
8月前
|
编译器 C++
内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)。
内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)
47 1
|
8月前
|
存储 安全 编译器
【C语言】动态内存管理 -- -- 深入了解malloc、calloc、realloc、free、柔性数组(万字深入了解)
【C语言】动态内存管理 -- -- 深入了解malloc、calloc、realloc、free、柔性数组(万字深入了解)
110 0
【C语言】动态内存管理 -- -- 深入了解malloc、calloc、realloc、free、柔性数组(万字深入了解)
|
7月前
|
程序员 C语言 C++
【C语言】:柔性数组和C/C++中程序内存区域划分
【C语言】:柔性数组和C/C++中程序内存区域划分
51 0
|
8月前
|
程序员 编译器 C语言
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(下)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
54 0
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(下)
|
8月前
|
编译器 数据库 C语言
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(上)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
55 0
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(上)
|
7月前
|
C语言
动态内存开辟(下)
动态内存开辟(下)
32 0
|
7月前
|
编译器 C语言
动态内存开辟(上)
动态内存开辟(上)
33 0