精华内容
下载资源
问答
  • (十二)C语言动态内存分配
    2016-12-22 12:25:15

    上一次记录了一下所谓的静态内存分配,我们可以看出静态内存分配有很多问题,大部分情况下我们不希望自己所做的工作白费,也就是内存被回收,除了确定了没用,所以我们该如何做呢?  C语言提供了动态内存分配,就是自己手动申请内存,但是也需要手动去释放内存。

    语法:使用malloc(int)关键字类申请一块内存,参数为要申请内存的大小,单位为byte

    #include <stdio.h> 
    #include<stdlib.h>
    
    void swipe(int** p){
    	//动态申请一块内存 
    	int *tempPoint = malloc(sizeof(int)); 
    	//给这块内存赋值为999 
    	*tempPoint = 999;
    	//指针p的值赋值为tempPoint中存储的内存地址。 
    	*p = tempPoint;
    	
    }
    
    void main(){
    	int i = 100;
    	int *p = &i;
    	swipe(&p); 
    	Sleep(10); 
    	printf("*p的:%d\n",*p);
    	printf("*p的:%d\n",*p);
    	printf("*p的:%d\n",*p);		
    }

    程序运行结果:

    *p的:999
    *p的:999
    *p的:999

    可以看出来,就算是延迟了也没有问题了。

     但是需要手动释放内存:

    语法:free(指针变量名);

    #include <stdio.h> 
    #include<stdlib.h>
    
    void swipe(int** p){
    	//动态申请一块内存 
    	int *tempPoint = malloc(sizeof(int)); 
    	//给这块内存赋值为999 
    	*tempPoint = 999;
    	//指针p的值赋值为tempPoint中存储的内存地址。 
    	*p = tempPoint;
    	
    }
    
    void main(){
    	int i = 100;
    	int *p = &i;
    	swipe(&p); 
    	Sleep(10); 
    	printf("*p的:%d\n",*p);
    	printf("*p的:%d\n",*p);
    	printf("*p的:%d\n",*p);
    	//因为这个指针p的值存储的是在swipe方法中动态申请的内存地址,所以释放这个指针变量p中存储的值对应的内存地址,就释放了swipe中开辟的那一块内存地址。 
    	free(p);		
    	printf("*p的:%d\n",*p);
    }

    运行结果:

     

    *p的:999
    *p的:999
    *p的:999
    *p的:12255568




    
    更多相关内容
  • C语言 动态内存分配详解 动态内存分配涉及到堆栈的概念:堆栈是两种数据结构。堆栈都是数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。 栈(操作系统):由操作系统自动分配释放 ,...
  • C语言动态内存分配的详解 1.为什么使用动态内存分配 数组在使用的时候可能造成内存浪费,使用动态内存分配可以解决这个问题。 2. malloc和free C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和...
  • C语言 动态内存分配

    2022-03-28 16:58:08
    C语言 动态内存分配一、动态内存分配函数1.1 malloc和free函数 前言:之前学习了数组,数组的元素储存在内存中连续位置。在声明数组时必须要指定数组的元素个数,即数组空间大小在声明时已经确定了。但是需存放的...


    前言:之前学习了数组,数组的元素储存在内存中连续位置。在声明数组时必须要指定数组的元素个数,即数组空间大小在声明时已经确定了。但是需存放的元素个数常常在运行时才能知道(取决于输入的数据)。这会有几个缺点: 1. 当输入元素个数大于数组声明的元素个数时会带来意想不到错误 2. 当输入元素个数小于数组声明的元素个数时会带来内存空间的浪费 3. 数组大小不能动态调整。
    C语言提供了相关的动态内存分配函数,需要多大内存空间就分配多大内存空间,并且可以动态调整已分配的内存空间大小

    一、动态内存分配函数

    使用下面相关动态内存函数需要引用头文件 <stdlib.h>

    1.1 malloc和free函数

    malloc函数功能:
    向内存申请指定大小的连续内存空间,申请成功返回该空间起始地址,申请失败返回NULL指针

    库函数malloc声明
    void* malloc (size_t size);
    返回值:申请成功返回该空间起始地址,申请失败返回NULL指针,因为不知道申请的空间要存放什么类型数据所以返回void*类型
    size: 申请分配的内存大小,单位为字节

    注意:
    1. malloc返回值有可能是NULL指针,使用前需要检查
    2. malloc申请的空间并没有被初始化

    free函数功能:
    释放申请的动态内存分配的空间(即malloc、calloc、realloc函数申请的空间)

    库函数free声明
    void free (void* ptr);
    ptr : 指向先前用malloc、calloc或realloc分配的内存块的指针

    注意:
    1.如果 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的
    2. 如果ptr 是NULL指针,则函数什么事都不做
    3. 只会释放ptr指向空间的值,但ptr本身不会被置空

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	//申请10个int类型大小空间,10 * sizeof(int)相对于sizeof(40)更具有移植性
    	//由于malloc返回值为void*类型,所以强制类型转换为int*类型
    	int* p = (int*)malloc(10 * sizeof(int));
    	if (p == NULL) //空间申请失败则退出
    	{
    		return -1; 
    	}
    	int i = 0;
    	for (i = 0; i < 10; i++) //打印这10个元素
    	{
    		printf("%d ", *(p + i));
    	}
    	printf("\n");
    	for (i = 0; i < 10; i++) //对数组元素赋值
    	{
    		*(p + i) = i;
    	}
    	for (i = 0; i < 10; i++) //打印这10个元素
    	{
    		printf("%d ", *(p + i));
    	}
    	printf("\n");
    	free(p); //释放p所指向动态内存分配的空间
    	p = NULL;//将p置为NULL指针,防止访问一个已释放的空间
    	return 0;
    }
    

    输出

    -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451 -842150451
    0 1 2 3 4 5 6 7 8 9
    

    1.2 calloc函数

    calloc函数功能:
    calloc函数与malloc函数功能一样,区别主要在于calloc会对分配的空间初始化为0,另外它们请求内存大小的方式不同

    库函数calloc声明
    void* calloc (size_t num, size_t size);
    返回值:申请成功返回该空间起始地址,申请失败返回NULL指针,因为不知道申请的空间要存放什么类型数据所以返回void*类型
    num:元素个数
    size: 元素大小
    申请内存空间大小=num*size

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int* p = (int*)calloc(10,sizeof(int));
    	if (p == NULL) //空间申请失败则退出
    	{
    		return -1;
    	}
    	int i = 0;
    	for (i = 0; i < 10; i++) //打印这10个元素
    	{
    		printf("%d ", *(p + i));
    	}
    	printf("\n");
    	for (i = 0; i < 10; i++) //对数组元素赋值
    	{
    		*(p + i) = i;
    	}
    	for (i = 0; i < 10; i++) //打印这10个元素
    	{
    		printf("%d ", *(p + i));
    	}
    	printf("\n");
    	free(p); //释放p所指向动态内存分配的空间
    	p = NULL;//将p置为NULL指针,防止访问一个已释放的空间
    	return 0;
    }
    

    输出

    0 0 0 0 0 0 0 0 0 0
    0 1 2 3 4 5 6 7 8 9
    

    使用malloc还是calloc函数取决是否要对动态内存分配的空间初始化

    1.3 realloc函数

    realloc函数功能:
    realloc对动态内存空间大小进行扩大或缩小

    库函数realloc声明
    void* realloc (void* ptr, size_t size);
    返回值:返回调整后空间的起始地址,调整失败返回NULL指针
    ptr:指向先前用malloc、calloc或realloc分配的内存块的指针
    size:动态内存空间新大小,单位为字节

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int* p = (int*)malloc(10 * sizeof(int));
    	if (p == NULL) //空间申请失败则退出
    	{
    		return -1;
    	}
    	int i = 0;
    	for (i = 0; i < 10; i++) //对数组元素赋值
    	{
    		*(p + i) = i;
    	}
    	int* ptr = realloc(p, 20 * sizeof(int)); //对动态内存大小进行调整
    	if (ptr == NULL) //调整失败并不影响原本p指向空间
    	{
    		printf("空间调整失败\n");
    	}
    	else
    	{
    		p = ptr; //调整成功,p指向调整后空间起始地址
    		ptr = NULL;
    		for (i = 10; i < 20; i++) //对数组元素赋值
    		{
    			*(p + i) = i;
    		}
    		for (i = 0; i < 20; i++) //打印数组元素
    	    {
    		    printf("%d ", *(p + i));
    	    }
    	}
    	
    	free(p); //释放p所指向动态内存分配的空间
    	p = NULL;//将p置为NULL指针,防止访问一个已释放的空间
    	return 0;
    }
    

    输出

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    

    在这里插入图片描述

    二、常见的动态内存错误

    2.1 对NULL指针进行解引用操作

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int* p = (int*)malloc(100000000000000000 * sizeof(int));
    	*p = 10; //没有对p是否非NULL检查
    	return 0;
    }
    

    申请动态内存分配失败,p为NULL指针,对p解引用修改存储的值会错误

    2.2 动态内存分配空间的越界访问

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int* p = (int*)malloc(10 * sizeof(int));
    	if (p == NULL)
    	{
    		return -1;
    	}
    	int i = 0;
    	for (i = 0; i <= 10; i++)
    	{
    		*(p+i) = i;
    	}
    	free(p);
    	p = NULL;
    	return 0;
    }
    

    当i=10,*(p+i)越界访问了

    2.3 对非动态内存分配的空间free释放

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int i = 10;
    	int* p = &i;
    	free(p);
    	p = NULL;
    	return 0;
    }
    

    p指向空间不是动态内存分配的空间

    2.4 对动态内存分配的空间的一部分free释放

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int* p = (int*)malloc(10 * sizeof(int));
    	if (p == NULL)
    	{
    		return -1;
    	}
    	free(p+5);
    	p = NULL;
    	return 0;
    }
    

    p+5指向空间是动态内存分配的空间的一部分

    2.5 对已经free的动态内存分配空间访问或再次free

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int* p = (int*)malloc(10 * sizeof(int));
    	free(p);
    	*p = 10; //对已经free的动态内存分配空间访问
    	free(p);//对动态内存分配空间多次free释放
    	p = NULL;
    	return 0;
    }
    

    2.6 内存泄漏

    当申请的动态内存空间不需要时应该被释放,这样可以重新分配使用。申请的空间在使用完毕后不free释放将引起内存泄漏。内存泄漏将一点点榨干可用内存,最终导致系统崩溃

    #include <stdio.h>
    #include <stdlib.h>
    void test()
    {
    	int* p = (int*)malloc(10*sizeof(int));
    }
    int main()
    {
    	while(1)
    	{
    		test();
    		//业务处理,满足条件则退出while循环
    	}
    	return 0;
    }
    

    当业务处理没有满足条件则while为死循环,每次循环都会申请内存空间,最终将系统崩溃

    展开全文
  • 1. 动态内存分配的意义 (1)C 语言中的一切操作都是基于内存的。 (2)变量和数组都是内存的别名。  ①内存分配由编译器在编译期间决定  ②定义数组的时候必须指定数组长度  ③数组长度是在编译期就必须确定的 (3)...
  • 引言:对于指针,正确的分配动态内存是十分重要的,本文将着重阐述动态内存分配函数malloc,calloc,realloc以及memset的用法。  一、对于malloc,在终端输入 #:man malloc可以知道函数原型是:  Void *calloc...
  • C语言动态内存分配函数

    万次阅读 多人点赞 2019-06-02 23:46:57
    目录 1.malloc()2.free()3.calloc()4.realloc()5....所开辟的内存是在栈中开辟的固定大小的 ,如a是4字节 ,数组b是40字节 ,并且数组在申明时必须指定其长度 , 因为数组的内存是在编译时分配好的 . 如果我们想在...

    目录

    1.malloc()
    2.free()
    3.calloc()
    4.realloc()
    5.小结


     在C中我们开辟内存空间有两种方式 :
    1.静态开辟内存 : 例如:

    int a;
    int b[10];

     这种开辟内存空间的特点是
    所开辟的内存是在栈中开辟固定大小的 ,如a是4字节 ,数组b是40字节 ,并且数组在申明时必须指定其长度 , 如果是全局数组的话,内存是在编译时分配好的,如果是局部变量数组的话,运行时在栈上静态分配内存。不管是全局数组还是局部数组,它们都有一个特点,那就是数组大小是确定的,是代码中写死的。那如果我们想在程序运行时才确定一个数组的大小 , 前两种在栈上分配内存的方法显然是不行的 , 举个例子 :

    int n;
    scanf("%d", &n);
    int a[n];

    这样编写会在编译时出错 , 编译器会提醒[ ]中应为常量表达式 , 在C中定义数组时可以用的有以下几种 ,例:

    #define N 10
    enum NUM{
    	M=10
    };
    int a1[N];
    int a2[10];
    int a3[M];

    需要注意的是 ,C中const int n =10 ; n并不能作为数组长度定义数组 , 但C++中则可以 , 
    但我们对于开辟空间的需求 , 往往不限于此 , 最常见的定义数组时数组大小在程序运行时才知道的 , 静态开辟就已经无能为力 . 当然有静态开辟 ,肯定也有动态开辟 ,接下来我们就来看动态开辟内存空间

    2.动态开辟内存 :
    在C中动态开辟空间需要用到三个函数 :
    malloc(), calloc(), realloc() ,这三个函数都是向堆中申请的内存空间.
    在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 需要我们手动释放 ,就需要free()函数来完成.
    下面让我们来看看这几个函数各自的特点, 用法, 区别, 联系.

    1.malloc()

    void * malloc(size_t size)

    1).malloc()函数会向中申请一片连续可用内存空间
    2).若申请成功 ,,返回指向这片内存空间的指针 ,若失败 ,则会返回NULL, 所以我们在用malloc()函数开辟动态内存之后, 一定要判断函数返回值是否为NULL.
    3).返回值的类型为void*型, malloc()函数并不知道连续开辟的size个字节是存储什么类型数据的 ,所以需要我们自行决定 ,方法是在malloc()前加强制转 ,转化成我们所需类型 ,如: (int*)malloc(sizeof(int)*n).
    4).如果size为0, 此行为是未定义的, 会发生未知错误, 取决于编译器

    具体怎么用呢 ,举个例子 .

    int *p = NULL;
    int n = 0;
    scanf("%d", &n);
    p = (int*)malloc(sizeof(int) * n);
    if(p != NULL){
        //....需要进行的操作
    }
    

    这时就相当于创建了一个数组 p[n] ,这个n的值并不需要像定义一个普通数组一样必须是常量, 可以使程序运行时得出的, 或是用户输入的


     2.free()

    void free(void* ptr)
    在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 如果我们不手动释放, 直到程序运行结束才会释放, 这样就可能会造成内存泄漏, 即堆中这片内存中的数据已经不再使用, 但它一直占着这片空间, (通俗说就是就是占着茅坑不拉屎), 所以当我们申请的动态内存不再使用时 ,一定要及时释放 .

    1).如果ptr没有指向使用动态内存分配函数分配的内存空间,则会导致未定义的行为。
    2).如果ptr是空指针,则该函数不执行任何操作。
    3).此函数不会更改ptr本身的值,因此它仍指向相同(现在已经无效)的位置(内存)
    4).free()函数之后需要将ptr再置空 ,即ptrNULL;如果不将ptr置空的话 ,后面程序如果再通过ptr会访问到已经释放过无效的或者已经被回收再利用的内存, 为保证程序的健壮性, 一般我们都要写ptrNULL;

    注意 : free()不能重复释放一块内存, 如:

    free(ptr);
    free(ptr);

     是错的, 已经释放过的内存不能重复释放, 会出现内存错误 .

    free()具体用法, 举个例子 :

    int *p = NULL;
    int n = 0;
    scanf("%d", &n);
    p = (int*)malloc(sizeof(int) * n);
    if(p != NULL){
        //....需要进行的操作
    }
    //操作完成 ,不再使用这片内存空间
    free(p);
    p = NULL;

     


     

     3.calloc()

    void * calloc(size_t num,size_t size)
    malloc()函数的区别只在于, calloc()函数会在返回地址之前将所申请的内存空间中的每个字节都初始化为0 .

    1).calloc()函数功能是动态分配num个大小(字节长度)为size的内存空间 .
    2).若申请成功 ,,返回指向这片内存空间的指针 ,若失败 ,则会返回NULL, 所以我们在用calloc()函数开辟动态内存之后, 一定要判断函数返回值是否为NULL.
    3).返回值的类型为void*型, calloc()函数虽然分配numsize大小的内存空间 ,但还是不知道存储的什么类型数据 ,所以需要我们自行决定 ,方法是在calloc()前加强制转 ,转化成我们所需类型 ,如: (int*)calloc(num, sizeof(int)).
    4).如果sizenum有一个或都为0, 此行为是未定义的, 会发生未知错误, 取决于编译器

    所以如何我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成这个需求。
    例如 :


    4.realloc()

    void * realloc(void * ptr,size_t size)

    realloc()函数让动态内存管理更加灵活 .在程序运行过程中动态分配内存大小,  如果分配的太大 ,则浪费空间, 如果太小, 可能还是会出现不够用的情况 .为了合理的利用内存,我们一定会对内存的大小做灵活的调整。那realloc() 函数就可以做到对动态开辟内存大小的调整(既可以往大调整, 也可以往小了调整) .

    1).ptr为需要调整的内存地址
    2).size为调整后需要的大小(字节数)
    3).若调整成功, 返回值为调整大小后内存的起始位置(也就是指向调整后内存的指针), 若失败(当没有内存可以分配时, 一般不会出现), 则返回NULL, 所以还是要对返回值判空
    4).如果ptr是空指针, 则和malloc()函数一样作用一样

    注意 : realloc()函数在扩大内存空间时有两种情况
    1).ptr所指的内存后有足够的内存空间用来扩展 ,如图 :

    2).ptr所指内存后没有足够的空间来扩展 ,如图 :
     

    当第二种情况时, 若申请新的内存空间成功, 会将ptr所指向的内存中的内容拷贝到新的内存空间中, ptr所指向的内存会被释放, 返回新得内存地址, 若不成功 ,ptr 所指内存不会被释放, 函数返回NULL


    5.小结

    1).malloc()calloc()函数用法一样, 唯一的区别是calloc()会对所申请内存的每个字节初始化为0

    2).malloc()calloc(), realloc()申请的内存不再使用时 ,一定要用free()释放 ,否则会造成内存泄漏

    3).p = realloc(ptr, size)函数返回值不为空时, 释放内存时不需写free(ptr) ,只需写free(p) 

     

     

    展开全文
  • 在程序的执行期间分配内存时,内存区域中的这个空间称为堆(heap)。还有另一个内存区域,称为栈(stack),...  C函数库中的malloc和free分别用于执行动态内存分配和释放。这两个函数的原型如下所示,他们都在头文件st
  • c语言怎么实现动态内存分配 我们经常会预先给程序开辟好内存空间,然后进行操作。 int arr[5] ; 对这个数组我们在定义的时候必须给提前开辟好空间,并且在程序执行的过程中,这个开辟的内存空间是一直存在的,除非...
  • 引言:对于指针,正确的分配动态内存是十分重要的,本文将着重阐述动态内存分配函数malloc,calloc,realloc以及memset的用法。  一、对于malloc,在终端输入 #:man malloc可以知道函数原型是:  Void *calloc...
  • C语言实现内存管理,实现malloc() ,free(), 但不会不会像标准库的动态内存分配函数容易引起内存崩溃。
  • C语言动态内存分配研究及应用.pdf
  • c语言动态内存分配

    千次阅读 2019-01-03 23:00:21
    这些内存中,有些是自动分配的(栈),有些是在编译时就确定好的(静态区),c语言还可以实现动态的/运行时的内存分配,提高程序的灵活性。 c语言动态内存分配的主要工具是stdlib.h中的malloc()、calloc()和free()...

    动态内存分配是许多高级程序设计技巧的关键。

    所有程序都必须留下足够的内存来存储程序使用的数据。这些内存中,有些是自动分配的(栈),有些是在编译时就确定好的(静态区),c语言还可以实现动态的/运行时的内存分配,提高程序的灵活性。

    c语言动态内存分配的主要工具是stdlib.h中的malloc()、calloc()和free()函数。

    malloc()函数会向操作系统请求内存块,并返回内存块的首地址。可以用一个指针变量保存这个地址。
    这里注意的是,这个内存块是匿名的,也就是不像int x 那样,x为内存地址的标识符。
    地址的类型为通用指针void *,我们需要为其强制类型转换。但申请失败时,返回值为NULL,所以我们申请完内存后,需要判断是否申请成功。
    malloc的参数为内存的字节大小。

    calloc()函数与malloc函数大体相同,calloc函数接受两个参数,单元数量和单元大小,并且内存块中的值为0;

    有借有还再借不难,free()函数用于释放申请的内存。如果忘记释放,那么可能把指向该内存块的指针搞丢了,我们再也无法操作这个内存,这就是内存泄露问题。

    下面是c primer plus 中的一个示例程序,程序动态分配由用户制定大小和值的double 数组,并把数组打印出来

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
    	double *ptd = NULL;
    	int max;
    	int number;
    	int i = 0;
    
    	puts("What is the maximun number of type double entries?");
    	
    	if(scanf("%d", &max)!=1)
    	{	
    		puts("Number not correctly entered --bye.");
    		exit(EXIT_FAILURE);
    	}
    	
    	ptd = (double *) malloc(max*sizeof(double));
    	if(ptd == NULL)
    	{
    		puts("Memory allocation failed. Goodbye.");
    		exit(EXIT_FAILURE);	
    	}	
    	
    	puts("Enter the values (q to quit):");
    
    	while(i < max && scanf("%lf",&ptd[i]) == 1)
    		++i;
    	
    	printf("Here are you %d entries:\n",number = i);
    	for(i=0 ; i < number ;i++)
    	{
    		printf("%7.2f",ptd[i]);
    			if(i%7 ==6)
    			putchar('\n');	
    	}	
    	
    	if(i%7 !=0)
    		putchar('\n');
    	puts("Done.");
    	free(ptd);
    	ptd = NULL;
    
    	return 0;
    }
    

    下面是转载的

    calloc(), malloc(), realloc(), free(),alloca()

    内存区域可以分为栈、堆、静态存储区和常量存储区,局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。
    利用指针,我们可以像汇编语言一样处理内存地址,C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h。

    四个函数之间的有区别,也有联系,我们应该学会把握这种关系,从而编出精炼而高效的程序。

    在说明它们具体含义之前,先简单从字面上加以认识,前3个函数有个共同的特点,就是都带有字符”alloc”,就是”allocate”,”分配”的意思,也就是给对象分配足够的内存,” calloc()”是”分配内存给多个对象”,” malloc()”是”分配内存给一个对象”,”realloc()”是”重新分配内存”之意。”free()”就比较简单了,”释放”的意思,就是把之前所分配的内存空间给释放出来。
    void *calloc(size_t nobj, size_t size);

    分配足够的内存给nobj个大小为size的对象组成的数组, 并返回指向所分配区域的第一个字节的指针;
    若内存不够,则返回NULL. 该空间的初始化大小为0字节.
    char *p = (char *) calloc(100,sizeof(char));

    void *malloc(size_t size);

    分配足够的内存给大小为size的对象, 并返回指向所分配区域的第一个字节的指针;
    若内存不够,则返回NULL. 不对分配的空间进行初始化.
    char *p = (char *)malloc(sizeof(char));

    void *realloc(void *p, size_t size);

    将p所指向的对象的大小改为size个字节.
    如果新分配的内存比原内存大, 那么原内存的内容保持不变, 增加的空间不进行初始化.
    如果新分配的内存比原内存小, 那么新内存保持原内存的内容, 增加的空间不进行初始化.
    返回指向新分配空间的指针; 若内存不够,则返回NULL, 原p指向的内存区不变.
    char *p = (char *)malloc(sizeof(char));
    p= (char *)realloc(p, 256);

    void free(void *p);

    释放p所指向的内存空间; 当p为NULL时, 不起作用.
    p必先调用calloc, malloc或realloc.

    值得注意的有以下5点:

    (1)通过malloc函数得到的堆内存必须使用memset函数来初始化

    malloc函数分配得到的内存空间是未初始化的。因此,一般在使用该内存空间时,要调用另一个函数memset来将其初始化为全0,memset函数的声明如下:void * memset (void * p,int c,int n) ;

    该函数可以将指定的内存空间按字节单位置为指定的字符c,其中,p为要清零的内存空间的首地址,c为要设定的值,n为被操作的内存空间的字节长度。如果要用memset清0,变量c实参要为0。

    malloc函数和memset函数的操作语句一般如下:

    int * p=NULL;

    p=(int*)malloc(sizeof(int));

    if(p==NULL)

    printf(“Can’t get memory!\n”);

    memset(p,0,siezeof(int));

    (2)使用malloc函数分配的堆空间在程序结束之前必须释放

    从堆上获得的内存空间在程序结束以后,系统不会将其自动释放,需要程序员来自己管理。一个程序结束时,必须保证所有从堆上获得的内存空间已被安全释放,否则,会导致内存泄露。

    我们可以使用free()函数来释放内存空间,但是,free函数只是释放指针指向的内容,而该指针仍然指向原来指向的地方,此时,指针为野指针,如果此时操作该指针会导致不可预期的错误。安全做法是:在使用free函数释放指针指向的空间之后,将指针的值置为NULL。

    (3)calloc函数的分配的内存也需要自行释放

    calloc函数的功能与malloc函数的功能相似,都是从堆分配内存,它与malloc函数的一个显著不同时是,calloc函数得到的内存空间是经过初始化的,其内容全为0。calloc函数适合为数组申请空间,可以将size设置为数组元素的空间长度,将n设置为数组的容量。

    (4)如果要使用realloc函数分配的内存,必须使用memset函数对其内存初始化

    realloc函数的功能比malloc函数和calloc函数的功能更为丰富,可以实现内存分配和内存释放的功能。realloc 可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。realloc 并不保证调整后的内存空间和原来的内存空间保持同一内存地址。相反,realloc 返回的指针很可能指向一个新的地址。

    所以,在代码中,我们必须将realloc返回的值,重新赋值给 p :

    p = (int *) realloc(p, sizeof(int) *15);

    甚至,你可以传一个空指针(0)给 realloc ,则此时realloc 作用完全相当于malloc。

    int* p = (int *)realloc (0,sizeof(int) * 10); //分配一个全新的内存空间,

    这一行,作用完全等同于:

    int* p = (int *)malloc(sizeof(int) * 10);

    (5)关于alloca()函数

    还有一个函数也值得一提,这就是alloca()。其调用序列与malloc相同,但是它是在当前函数的栈帧上分配存储空间,而不是在堆中。其优点是:当 函数返回时,自动释放它所使用的栈帧,所以不必再为释放空间而费心。其缺点是:某些系统在函数已被调用后不能增加栈帧长度,于是也就不能支持alloca 函数。尽管如此,很多软件包还是使用alloca函数,也有很多系统支持它。

    总结:应用时候需要记得,只有calloc可以指定个数和大小,而且能够对分配内存进行初始化,其余函数均不会对内存进行初始化工作,需要自行调用memset()函数.

    展开全文
  • 大家好,今天简单讲一讲C语言中的动态内存分配。 截至目前,我们所使用的变量似乎都是在栈区(如局部变量、函数形参)和静态区(如全局变量、static修饰的变量),但是我们很早就知道除了栈区、静态区,在内存中...
  • C语言动态内存分配

    千次阅读 多人点赞 2022-01-28 17:20:06
    动态内存分配就那么回事儿!
  • 静态内存分配在编译时就对变量分配空间,而动态内存分配直到程序运行时再进行分配。 使用静态内存分配的变量有:全局变量和静态变量。 全局变量是直接在程序中定义而非在函数(包括main函数)中定义的变量。 静态...
  • C语言动态内存分配

    千次阅读 2021-07-21 22:06:46
    C语言动态内存分配 文章目录【C语言动态内存分配一、malloc 与free函数二、calloc三、realloc四、常见的动态内存的错误 本期,我们将讲解malloc、calloc、realloc以及free函数。 这是个动态内存分配函数的...
  • 动态内存分配:根据需要随时开辟,随时释放的内存分配方式。分配时机和释放时机完全由程序员决定,由于没有数据声明,这部分空间没有名字。无法像使用变量或数组那样通过变量名或数组名引用其中的数据,只能通过指针...
  • C语言 结构体动态内存分配

    千次阅读 2020-05-29 13:56:44
    结构体动态内存分配定义 可以用别名不用别名
  • 所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是...
  • #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int Differentiate(i) { return *(char*)&i; } int main() { int a = 0x01; int m = Differentiate(a); if (m == 1) { ...}
  • 要了解在C语言动态内存是如何分配的,我们首先要了解什么是内存动态分配,之前我们已经介绍过全局变量和局部变量,全局变量是分配内存中的静态存储区的,非静态的局部变量(包括形参)是分配内存中的动态存储...
  • 这种方式数组在申明时必须指定其长度,因为数组的内存是在编译时分配好的。 如果我们想在程序运行时才确定一个数组的大小,静态开辟内存空间的方法是不行的 例如: int n; scanf("%d",&n); int a[n]; 这样编写会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 198,736
精华内容 79,494
关键字:

c语言动态内存分配