C语言之动态分配内存

1. malloc()函数和free()函数

首先,我们应该知道。所有的程序都必须留出足够的内存空间来存储所使用的数据,所以我们常常会预先给程序开辟好内存空间,然后进行操作,但事实上另一种选择,能够让内存分配自己主动进行下去。

对于传统数组,会遇到这种问题:

int arr[5] ;

对这个数组我们在定义的时候必须给提前开辟好空间。而且在程序运行的过程中,这个开辟的内存空间是一直存在的。除非等到这个函数运行完成,才会将空间释放。

另一个问题就是这个数组在程序中无法被改动。

这些问题给我们造成了一些使用上的不方便,所以,C中提供了malloc()函数。

关于malloc()函数。这个函数它接受一个參数:就是所需的内存的字节数。然后malloc()找到可用内存中那一个大小适合的块。在这个过程中,malloc()能够来返回那块内存第一个字节的地址。所以。也就意味了我们能够使用指针来操作。malloc()能够用来返回数组指针、结构指针等等。所以我们须要把返回值的类型指派为适当的类型。当malloc()找不到所需的空间时。它将返回空指针。

例:

double *p;
p=(double*)malloc(30*sizeof(double));

在这个程序中,首先开辟了30个double类型的空间,然后把p指向这个空间的位置。在这里的指针是指向第一个double值。

并非我们所有开辟的30个double的空间。

这就和数组一样,指向数组的指针式指向数组首元素的地址,并非整个数组的元素。所以,在这里我们的操作也和数组是一样的,

p[0]就是第一个元素。p[2]就是第二个元素。

至此。我们就能够掌握到一种声明动态数组的方法。

int arr[n];
p=(int *)malloc(n*sizeof(int));
//我们在这里使用的时候要元素个数乘类型字节长度。这样就达到了动态开辟内存空间。

当我们使用malloc()开辟完内存空间以后,我们所要考虑的就是释放内存空间,在这里,C给我们提供了free()函数。

free()的參数就是malloc()函数所返回的地址,释放先前malloc()函数所开辟的空间。

例:

对于上面我们所开辟的空间进行释放,那么我们就能够这样

free(p);

程序还调用了exit()函数,这个函数是在内存分配失败时结束程序。

程序样例:


#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>//malloc()函数被包括在malloc.h里面
#include<stdlib.h>
int main(void)
{
    char*a = NULL;//声明一个指向a的char*类型的指针
    a = (char*)malloc(100 * sizeof(char));//使用malloc分配内存的首地址。然后赋值给a
    if (!a)//假设malloc失败。能够得到一些log
    {
        perror("malloc");
        return-1;
    }
    sprintf(a, "%s", "HelloWorld\n");//"HelloWorld\n"写入a指向的地址
    printf("%s\n", a);//输出用户输入的数据
    free(a);//释放掉使用的内存地址
    system("pause");
    return 0;//例2有无内存泄露?
}

这个程序主要用来检測malloc返回值条件有误。

在这里我们须要注意,在C中,类型指派(char *)是可选的,可是在C++中这个是必须有的,所以使用类型指派将使把C程序移植到C++更easy。

使用动态数组,主要是为了获得程序的灵活性。我们嗯能够须要多少个元素就让数组开辟多少个。。

不须要浪费空间

2.free()的重要性

在我们使用malloc()函数的时候。分配的内存是会添加的,当我们使用free()函数时,能够释放内存。
比如:
...

int main()
{
    double glad[2000];
    int i;
    ...
    for(i=0;i<1000;i++)
        gobble(glad,2000);
    ...
}
void gobble(double arr[],int n)
{
    double *temp=(double *)malloc(n*sizeof(double));
    ...
}

在这个程序其中我们使用了malloc()函数,可是我们没有使用free()函数,在这个程序中,我们首先进入gobble()函数,穿件了指针temp,而且使用了malloc()函数。可是除了gobble()函数之后,指针作为一个变量消失了,可是所开辟的内存是依旧存在的,我们依旧开辟了16000个字节的内存。

可是我们却无法去訪问这些内存。由于他们的地址不见了。由于没有调用free()函数,这段内存也不能再此使用了。

这样依次循环。总共运行for循环1000次。终于导致了程序总共16000000个字节的内存无法使用,这样。内存肯定已经溢出了。

这样就会出现我们所说的程序泄漏问题,而free()函数,正好攻克了这种的问题。

3.calloc()函数和realloc()函数

接下来。我们在认识两个关于内存分配的函数。calloc()函数和realloc()函数。

calloc()函数与malloc()函数有同样之处。也有类似之处。

例:

short *p;
newmem=(short *)calloc(1000,sizeof(short)); 

通过这个样例,我们能够知道calloc()函数有两个參数。而且这两个函数都是size_t类型(unsigned int类型)的数。

第一个參数在这里所说的是所须要开辟的内存单元数量。第二个參数是每一个单元的字节的大小。

void *calloc(size_t ,size_t);

calloc()函数另一个特性。它将块中的所有位都置为0。这也是calloc()函数和malloc()函数的差别,calloc()函数和malloc()函数的另外一个差别是他们请求内存数量的方式不一样。当然。free()函数也能够来释放calloc()函数分配的内存。

realloc()函数用来改动一个原先已经分配的内存的大小。使用这个函数,你能够让一块内存增大还是缩小。当扩大时。这块内存原先的内容会依旧保留,新添加的加入到原先的后面。缩小时,该内存的尾部部分内存去掉,剩余保留。

注意:对于realloc()函数。假设原先的内存无法改动。这时候realloc()函数再会分配一块内存。而且把原先那块内存的内容拷贝到上面去。

所以。使用了realloc函数以后,你这时候在使用的就该是realloc函数返回的新指针了。当realloc函数的第一个參数是NULL时,这时候我们能够把它当作是malloc()函数。

写博客已经半个月了,感觉问题还是非常多。希望大家多多指点。

时间: 2024-10-08 04:09:07

C语言之动态分配内存的相关文章

动态分配内存专题

我讲解一下c语言中动态分配内存的函数,可能有些初学c语言的人不免要问了:我们为什么要通过函数来实现动态分配内存呢?系统难道不是会自动分配内存吗??既然有人会问这样的问题,那么我在这里好好的讲解一下吧!首先让我们熟悉一下计算机的内存吧!在计算机的系统中有四个内存区域:1)栈:在栈里面储存一些我们定义的局部变量以及形参(形式参数):2)字符常量区:主要是储存一些字符常量,比如:char *p_str="cgat";其中"cgat"就储存在字符常量区里面:3)全局区:在全

C语言中二维数组如何申请动态分配内存

C语言中二维数组如何申请动态分配内存: 使用malloc函数,先分配第一维的大小,然后再循环分配每一维的大小 #include <stdio.h> #include <malloc.h> int main() { int **a; int i, j; a = (int**)malloc(sizeof(int*)*3);//为二维数组分配3行 for (i = 0; i < 3; ++i){//为每列分配4个大小空间 a[i] = (int*)malloc(sizeof(int

C语言-动态分配内存对任意个字符串进行排序

//动态分配内存对输入的任意字符串排序 #include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<string.h> //比较大小 //int str_compare(const char* src,const char* dst) //{ // int ret = 0; // if (src == dst) // { // return 0; // } // if (dst == NU

c语言中的内存管理

一:内存分为5大区域 栈区     --  存放局部变量 堆区     --  程序运行过程中,动态分配的内存 BSS区    --  未初始化的全局变量和静态变量 数据段    --  已经初始化的全局变量和静态变量 代码段    --  程序编译产生的二进制的数据 内存分配方式: ·1)静态分配,在编译的阶段分配的内存     int a = 10;    静态分配的内存在程序结束后会自动释放 2)动态分配,在程序的运行过程中进行的内存分配 ,动态分配的内存一般存储在堆中,程序结束后内存不会

C语言的代码内存布局详解

一个程序本质上都是由 BSS 段.data段.text段三个组成的.这样的概念在当前的计算机程序设计中是很重要的一个基本概念,而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大小分配,存储单元占用空间大小的问题. BSS段:在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段:在采用段式内存管理的架构中,数据段(da

C语言的代码内存布局

一个程序本质上都是由 BSS 段.data段.text段三个组成的.这样的概念在当前的计算机程序设计中是很重要的一个基本概念,而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大小分配,存储单元占用空间大小的问题. BSS段:在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段:在采用段式内存管理的架构中,数据段(da

C语言变量声明内存分配

转载: C语言变量声明内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.程序结束时由编译器自动释放. 2.堆区(heap) — 在内存开辟另一块存储区域.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵. 3.全局区(静态区)(static)—编译器编译时即分配内存.全局变量和静态变量

[转载]C语言程序的内存分配方式

"声明一个数组时,编译器将根据声明所指定的元素数量为数量为数组保留内存空间."其实就是编译器在编译的过程中,会加入几条汇编指令在程序里处理内存分配,并不是说编译时就分配了内存,不要理解错了. ------------------- 1.内存分配方式 内存分配方式有三种: [1]从静态存 储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建. 在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结

数据结构基础(1)--数组C语言实现--动态内存分配

数据结构基础(1)--数组C语言实现--动态内存分配 基本思想:数组是最常用的数据结构,在内存中连续存储,可以静态初始化(int a[2]={1,2}),可以动态初始化 malloc(). 难点就是数组在删除或者插入元素的时候,要移动元素的坐标不好确定.规律: 1.如果要在数组中第pos个位置插入一个元素(应该从后面开始移动) for( i=cnu;i>=pos;i--) pBase[i]=pBase[i-1]; 2.删除数组第pos位置的元素 for(i=pos+1;i<=cnu;i--)