4、动态内存分配(*****)

一、传统数组的缺点(*****)

1).数组长度必须事先制定,且只能是常整数,不能是变量
  例子:

    int a[5];//oK
    int len=5;int a[len];//error

2).传统形式定义的数组,该数组的内存程序员无法手动释放,在一个函数运行期间,系统为该函数中数组所分配的空间会一直存在,
直到该函数运行完毕时,数组的空间才会被系统释放

3).数组的长度一旦定义,其长度就不能在更改数组的长度不能在函数运行的过程中动态的扩充或缩小

4).A函数定义的数组,在A函数运行期间可以被其它函数使用,但A函数运行完毕之后,A函数中的数组将无法在被其他函数使用
传统方式定义的数组不能跨函数使用

二、为什么需要动态分配内存

  动态内存很好的解决了传统数组的这4个缺陷
  传统数组也叫静态数组

三、动态数组的构造

1、malloc函数的用法
/*
    malloc 的使用
    malloc 是 memory(内存) allocate(分配)的缩写
*/

# include <stdio.h>
# include <malloc.h>  //不能省

int main(void)
{
    int i = 5; //分配了4个字节 静态分配   11 行
    int * p = (int *)malloc(4); //12行
        /*
            1. 要使用malloc函数,必须添加malloc.h这个头文件
            2. malloc函数只有一个形参,并且形参是整型
            3. 4表示请求系统为本程序分配4个字节
            4. malloc函数只能返回第一个字节的地址,所以需要强制类型转换告诉别人第一个字节的地址
               指向的变量占几个字节
            5. 12行分配了8个字节, p变量占4个字节, p所指向的内存也占4个字节
            6. p本身所占的内存是静态分配的, p所指向的内存是动态分配的
        */

    *p = 5; //*p 代表的就是一个int变量, 只不过*p这个整型变量的内存分配方式和11行的i变量的分配方式不同
    free(p); //freep(p)表示把p所指向的内存给释放掉  p本身的内存是静态的,不能由程序员手动释放,
                                   //p本身的内存只能在p变量所在的函数运行终止时由系统自动释放
    printf("同志们好!\n");

    return 0;
}

2、通过被调函数修改主调函数变量的值

/*-------------------------------------
    通过被调函数修改主调函数变量的值
---------------------------------------*/

# include <stdio.h>
# include <malloc.h>

void f(int * q)
{
    //*p = 200; //error
    //q = 200;
    //**q = 200;  //error
    *q = 200;
    //free(q);  //把q所指向的内存释放掉  本语句必须的注释掉,否则会导致第20行的代码出错,因为*p代表的是指向的地址,                             // 这里q会把*p的动态内存释放掉,访问权限就不属于这个程序了。
}

int main(void)
{
    int * p = (int *)malloc(sizeof(int)); //sizeof(int)返回值是int所占的字节数
    *p = 10;

    printf("%d\n", *p);  //10
    f(p);  //p是int *类型
    printf("%d\n", *p);  //200    第20行

    return 0;
}

3、动态内容分配举例--动态数组的构造

假设动态构造一个int型一维数组[至少保证要看懂]

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

本语句分配了两块内存,一块内存是动态分配的,总共len个字节,另一块是静态分配的,并且这块静态内存是p变量本身所占的内存,总共4个字节

1)malloc只有一个int型的形参,表示要求系统分配的字节数
2)malloc函数的功能是请求系统1en个字节的内存空间,如果请求分配成功,则返回第一个字节的地址,如果分配不成功,则返回NULL
malloc函数能且只能返回第一个字节的地址,所以我们需要把这个无任何实际意义的第一个字节的地址(俗称干地址)转化为一个有实际意义的地址,
因此,malloc前面必须加(数据类型*),表示把这个无实际意义的第一个字节的地址转化为相应类型的地址。如:

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

表示将系统分配好的50个字节的第一个字节的地址转化为int*型的地址,更准确的说是把第一个字节的地址转化为四个字节的地址,这样p就指向了第一个的四个字节,p+1就指向了第2个的四个字节,p+i就指向了第i+1个的4个字节。p[0]就是第一个元素,p[i]就是第i+1个元素。

  double*p=(double*)malloc(80);

表示将系统分配好的80个字节的第一个字节的地址转化为double*型的地址,更准确的说是把第一个字节的地址转化为8个字节的地址,这样p就指向了第一个的8个字节,p+1就指向了第2个的8个字节,p+i就指向了第i+1个的8个字节。p[0]就是第一个元素,p[i]就是第i+1个元素。

4、freep(p);
表示把p所指向的内存给释放掉p本身的内存是静态的,不能由程序员手动释放,p本身的内存只能在p变量所在的函数运行终止时。
5、由系统自动释放静态内存和动态内存的比较【重点】
  静态内存是由系统自动分配,由系统自动释放静态内存是在栈分配的。
  动态内存是由程序员手动分配,手动释放动态内存是在堆分配的。
6、跨函数使用内存的问题【重点】
  静态内存不可以跨函数使用
  所谓静态内存不可以跨函数使用更准确的说法是:静态内存在函数执行期间可以被其它函数使用,静态内存在函数执行完毕之后就不能再被其他函数使用了。
  动态内存可以跨函数使用,动态内存在函数执行完毕之后仍然可以被其他函数使用。

/*-------------------------------------
    动态一维数组示例
---------------------------------------*/

# include <stdio.h>
# include <malloc.h>

int main(void)
{
    int a[5]; //如果int占4个字节的话,则本数组总共包含有20个字节,每四个字节被当做了一个int变量来使用
    int len;
    int * pArr;
    int i;

    //动态的构造一维数组
    printf("请输入你要存放的元素的个数: ");
    scanf("%d", &len);
    pArr = (int *)malloc(4 * len);  //第12行  本行动态的构造了一个一维数组, 该一维数组的长度是len, 该数组的数组名是pArr,
                                            //该数组的每个元素是int类型  类似于 int pArr[len];

    //对一维数组进行操作,  如:对动态一维数组进行赋值
    for (i=0; i<len; ++i)
        scanf("%d", &pArr[i]);

    //对位一维数组进行输出
    printf("一维数组的内容是:\n");
    for (i=0; i<len; ++i)
        printf("%d\n", pArr[i]);

    free(pArr); //释放掉动态分配的数组

    return 0;
}

/*----------------------------------------------
    打印结果:
                请输入你要存放的元素的个数: 6
            1 2 3 4 5 6
            一维数组的内容是:
            1
            2
            3
            4
            5
            6
            Press any key to continue
------------------------------------------------*/

原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/12639930.html

时间: 2024-11-13 08:08:13

4、动态内存分配(*****)的相关文章

C++动态内存分配

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 C / C ++中的动态内存分配是指程序员手动执行内存分配, 动态分配的内存分配给堆,非静态和局部变量获取在Stack上分配的内存.详情查看上篇博文:C程序的内存布局. 什么是应用程序? 动态分配的

【C语言天天练(九)】动态内存分配

引言:数组的元素存储于内存中连续的位置上.当一个数组被声明时.它所须要的内存在编译时就被分配. 可是,我们能够使用动态内存分配在执行时为它分配内存. 一块内存的生命周期能够分为四个阶段:分配.初始化.使用.释放. 内存的分配一般使用C函数库里的malloc函数(原型:void *malloc(size_t size)). 关于malloc函数应该注意一下几点: 1.malloc的參数就是须要分配的内存的字节数. 2.malloc所分配的是一块连续的内存. 3.分配成功.则返回指向分配内存起始地址

SQLite剖析之动态内存分配

SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.以及保存查询结果.我们做了很多努力来让SQLite的动态内存分配子系统可靠.可预测.健壮并且高效.本文概述SQLite的动态内存分配,软件开发人员在使用SQLite时可以据此获得最佳性能. 1.特性    SQLite内核和它的内存分配子系统提供以下特性:    (1)对内存分配失败的健壮处理.如果一个内存分配请求失败(即malloc()或realloc()返回NULL),SQ

继承和动态内存分配

假设基类使用了动态内存分配,而且定义了析构函数.复制构造函数和赋值函数,但是在派生类中没有使用动态内存分配,那么在派生类中不需要显示定义析构函数.复制构造函数和赋值函数. 当基类和派生类采用动态内存分配时,派生类的析构函数.复制构造函数.赋值运算符都必须使用相应的基类方法来处理基类元素.这种要求是通过三种不同的方式来满足的.对于析构函数.这是自动完成的,也就是说在派生类的析构函数中无需显示调用基类的析构函数.对于构造函数,这是通过在初始化成员类别中调用基类的复制构造函数来完成的,如果不这样做,将

【Cpp】考点·堆栈&amp;动态内存分配

动态内存分配 堆内存分配与释放 C/C++定义了四个内存区间:代码区,全局变量与静态变量区,局部变量区(栈区),动态内存区(堆区) 通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间.这种内存分配称为静态存储分配.有些操作对象只在程序运行时才确定,这样编译时无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为动态存储分配.所有动态存储分配都在堆区中进行. 当程序运行到需要一

C++ 动态内存分配(6种情况,好几个例子)

1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间.这种内存分配称为静态存储分配: 有些操作对象只在程序运行时才能确定,这样编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为动态存储分

28._动态内存分配

动态内存分配 传统数组的缺点(静态内存分配):   1.数组长度必须事先指定,且只能是常整数,不能是变量    例子:     int a[5]; //OK     int len = 5; int a[len]; //error   2.传统形式定义的数组,该数组的内存程序员无法手动编    程释放,在一个函数运行期间,系统为该函数中数组所     分配的空间会一直存在,直到该函数运行完毕时,数组    元素所占存储空间才会被系统释放 3.数组的长度一旦定义,长度就能被改变     4.A函数

一维和二维数组 动态内存分配

一维数组的动态内存分配 #include "stdafx.h" #include <iostream> using namespace std; int main() { int length,i; int *p; cin>>length; p=new int[length]; for(i=0;i<length;i++) { p[i]=i; //不要写成*p[i]=i; cout<<p[i]<<endl; //不要写成cout<

Lesson(DynamicMerry)动态内存分配

//  main.m //  1-27随堂笔记 //讲师: 小辉 //笔者: 王学文 //  Created by lanouhn on 15/1/27. //  Copyright (c) 2015年 lanouhn. All rights reserved. //动态内存分配(DynamicMerry) #import <Foundation/Foundation.h> void test() { int x = 10; int y = 20; } //函数返回栈区的数据,是不安全的;一i

动态内存分配函数与释放函数

(1)分配函数 void *malloc(sizeof(unsigned size) 功能:在内存的动态存储区中分配一块长度位size的连续空间. 返回值:指针,存放被分配内存的起始地址.若未申请到空间,则返回NULL(0). void *:指向任何类型的数据,在使用时,要进行强制类型转换. 例如:int *malloc(sizeof(int)) struct student *malloc(sizeof(struct student)) (2)释放函数 void free(void *ptr)