[UE4]C 语言动态数组
在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。
动态数组,是相对于静态数组而言。静态数组的长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程序需要而重新指定大小。动态数组的内存空间是从堆(heap)上分配(即动态分配)的。是通过执行代码而为其分配存储空间。当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。
为什么要使用动态数组?
在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。
动态数组与静态数组的对比
对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!
对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则严重会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。
如何构建动态数组
遵循原则
申请的时候从外层往里层,逐层申请;
释放的时候从里层往外层,逐层释放。
构建所需指针
对于构建一维动态数组,需要一维指针;
对于二维,则需要一维,二维指针;
三维需要一,二,三维指针;
依此类推。
构建所需函数
| 函数原型 | 返 回 | 功能说明 |
| void *malloc(unsigned int size); | 成功:返回所开辟 空间首地址 失败:返回空指针 | 向系统申请 size字节的 堆空间 |
| void *calloc(unsigned int num, unsigned int size); | 成功:返回所开辟 空间首地址 失败:返回空指针 | 按类型申请 num个size字 节的堆空间 |
| void free(void *p); | 无返回值 | 释放p指向 的堆空间 |
| void *realloc(void *p,unsigned int size); | 成功:返回新开辟 空间首地址 失败:返回空指针 | 将p指向的 堆空间变为 size |
说明:
(1)规定为 void * 类型,这并不是说该函数调用后无返回值,而是返回一个结点的地址,该 地址的类型为void(无类型或类型不确定),即一段存储区的首址,其具体类型无法确定,只有使 用时根据各个域值数据再确定。可以用强制转换的方法将其转换为别的类型。例如:double *pd=NULL; pd=(double *)calloc(10,sizeof(double)); 表示将向系统申请10个连续的 double类型的存储空间,并用指针pd指向这个连续的空间的首地址。并且用(double)对calloc( ) 的返回类型进行转换,以便把double类型数据的地址赋值给指针pd。
(2)使用sizeof的目的是用来计算一种类型的占有的字节数,以便适合不同的编译器。
(3)由于动态分配不一定成功,为此要附加一段异常处理程序,不致程序运行停止,使用户 不知所措。通常采用这样的异常处理程序段: if(p==NULL) /* 或者if(!p)*/ { printf("动态申请内存失败!\n"); exit(1); //异 常退出 }
(4)这四个函数头文件均包含在中。
(5)分配的堆空间是没有名字的 只能通过返回的指针找到它。
(6)绝不能对非动态分配存储块使用free。也不能对同一块内存区同时用free释放两次。 如:free(p);free(p);
(7)调用 free() 时, 传入指针指向的内存被释放, 但调用函数的指针值可能保持不变, 因 为p是作为形参而传递给了函数。严格的讲, 被释放的指针值是无效的, 因为它已不再指向所申请 的内存区。这时对它的任何使用便可能会可带来问题。
malloc与calloc的区别
对于用malloc分配的内存区间,如果原来没有被使用过,则其中的每一位可能都是0;反之, 如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说, 使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内 存空间已被重新分配)可能会出现问题,因此在使用它之前必须先进行初始化(可用memset函数 对其初始化为0),但调用calloc()函数分配到的空间在分配时就已经被初始化为0了。 当你在calloc()函数和malloc()函数之间作选择时,你需考虑是否要初始化所分配的内存空 间,从而来选择相应的函数。
具体构建方法
以三维整型数组array[n1][n2][n3]为例。
先遵循从外层到里层,逐层申请的原则:
最外层指针是array,它是个三维指针,所指向的是array[],其为二维指针。所以给array
申请内存应:
array=(int***)calloc(n1,sizeof(int**));
次层指针是array[],它是个二维指针,所指向的是array[][],其为一维指针。所以给array[]
申请内存应:
for(i=;i<n1;i++)
{
array[i]=(int**)calloc(n2,sizeof(int*));
}
最内层指针是array[][],它是个一维指针,所指向的是array[][][],其是个整型常量。所以给array[][]申请内存应:
for(i=;i<n1;i++)
{
for(j=;j<n2;j++)
{
array[i][j]=(int*)calloc(n3,sizeof(int));
}
}
当然,你可以把它们整合在一起为:
int i,j,k;
int n1,n2,n3;
int ***array;
scanf("%d%d%d",&n1,&n2,&n3);
array=(int***)calloc(n1,sizeof(int**));
for(i=;i<n1;i++)
{
array[i]=(int**)calloc(n2,sizeof(int*));
for(j=;j<n2;j++)
{
array[i][j]=(int*)calloc(n3,sizeof(int));
for(k=;k<n3;k++)
{
array[i][j][k]=i+j+k+;
}
}
}
最后不要忘了释放这些内存,这要遵循释放的时候从里层往外层,逐层释放的原则。
分析过程可参考上面的解答,这里不再赘述。只给出代码吧:
for(i=;i<n1;i++)
{
for(j=;j<n2;j++)
{
free(array[i][j]);//释放第三维指针
}
}
for(i=;i<n1;i++)
{
free(array[i]);//释放第二维指针
}
free(array);//释放第一维指针
其余维的如四维创建过程大同小异,这里不再赘述。
[UE4]C 语言动态数组的更多相关文章
- c语言 动态数组
C语言中,在声明数组时,必须明确告诉编译器数组的大小,之后编译器就会在内存中为该数组开辟固定大小的内存.有些时候,用户并不确定需要多大的内存,使用多大的数组,为了保险起见,有的用户采用定义一个大数组的 ...
- 线性表之顺序存储结构(C语言动态数组实现)
线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链 ...
- C语言 动态数组实现
一.概述 C语言是不能直接定义动态数组的,数组必须在初始化时确定长度. 如果要在程序运行时才确定数组的长度,就需要在运行的时候,自己去向系统申请一块内存用动态内存分配实现动态数组. 二.动态内存分配函 ...
- C语言 · 动态数组的使用
从键盘读入n个整数,使用动态数组存储所读入的整数,并计算它们的和与平均值分别输出.要求尽可能使用函数实现程序代码.平均值为小数的只保留其整数部分. 样例输入: 5 3 4 0 0 2样例输出:9 1样 ...
- (2)redis的基本数据结构是动态数组
redis的基本数据结构是动态数组 一.c语言动态数组 先看下一般的动态数组结构 struct MyData { int nLen; ]; }; 这是个广泛使用的常见技巧,常用来构成缓冲区.比起指针, ...
- (待续)C#语言中的动态数组(ArrayList)模拟常用页面置换算法(FIFO、LRU、Optimal)
目录 00 简介 01 算法概述 02 公用方法与变量解释 03 先进先出置换算法(FIFO) 04 最近最久未使用(LRU)算法 05 最佳置换算法(OPT) 00 简介 页面置换算法主要是记录内存 ...
- c语言,动态数组
试着直接malloc一个2*3*4的空间来模拟数组: #include <stdio.h> #include <malloc.h> int main(void) { int** ...
- C语言基础 - 实现动态数组并增加内存管理
用C语言实现一个动态数组,并对外暴露出对数组的增.删.改.查函数 (可以存储任意类型的元素并实现内存管理) 这里我的编译器就是xcode 分析: 模拟存放 一个 People类 有2个属性 字符串类型 ...
- [C] 在 C 语言编程中实现动态数组对象
对于习惯使用高级语言编程的人来说,使用 C 语言编程最头痛的问题之一就是在使用数组需要事先确定数组长度. C 语言本身不提供动态数组这种数据结构,本文将演示如何在 C 语言编程中实现一种对象来作为动态 ...
随机推荐
- Python GIL 系列之再谈Python的GIL
1. 之前写过一篇<通过实例认识Python的GIL>的文章,感觉有些意犹未尽 2. 这次对例子作了些扩展,进一步的分析GIL对Python程序的影响 2.1 先来看例子: [python ...
- postman--安装及Interceptor插件
1. 官网安装(看网速-我下载的时候一直下载失败) 打开官网,https://www.getpostman.com 选择ios或者win 2. 非官网安装 https://pan.baidu. ...
- jenkins系列(9)--插件之Archive The Artifacts
点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...
- Tomcat结合nginx使用入门
Nginx: Nginx是一款高性能,轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 特点是:占有内存少,并发能力强. 反向代理服务器: 反向代理(Reverse ...
- [LeetCode&Python] Problem 590. N-ary Tree Postorder Traversal
Given an n-ary tree, return the postorder traversal of its nodes' values. For example, given a 3-ary ...
- 在有 UI 线程参与的同步锁(如 AutoResetEvent)内部使用 await 可能导致死锁
AutoResetEvent.ManualResetEvent.Monitor.lock 等等这些用来做同步的类,如果在异步上下文(await)中使用,需要非常谨慎. 本文将说一个在同步上下文中非常常 ...
- 《DSP using MATLAB》Problem 3.17
用差分方程两边进行z变换,再变量带换得到频率响应函数(或转移函数,即LTI系统脉冲响应的DTFT). 代码: %% ------------------------------------------ ...
- 转 MetaWeblog API 编写
如今,许多人都熟悉个人和公司或业界主办的博客.后者明显成为了传统公司和行业网站的下一代新兴产物.博客的内容涉及从简洁的特制产品公告和公共关系到实用且深刻的主题探索,这些主题可能对公司的产品或行业的未来 ...
- cocos2dx学习资料
[9秒原创]cocos2d-x——CCScrollView用法 http://www.9miao.com/thread-45619-1-1.html [9秒原创]cocos2d-x——场景切换效果示例 ...
- FastAdmin 开发第三天:认识目录
以下为标准 FastAdmin 安装后的目录 我们在运行命令时都是在这个目录. 我们所有的命令都在这个目录下面运行. 比如:安装前端组件,bower install 安装php 组件 composer ...