【C数据类型】动态数组的使用方法(总结)

C语言数据结构一:动态数组 C语言数据结构一:动态数组;可插值,可删除,可动态拓展容量。 阅读详情

概述:

  1. 本文主要介绍了C语言中的一维动态数组和二维动态数组的使用方式。
  2. 核心的库“stdlib.h”,核心的库函数“malloc()”。
  3. 代码量较多,文字叙述较少,但绝对通俗易懂。

Table of Contents

一维动态数组

malloc函数的使用

辨析

实例

二维动态数组

二维动态数组的使用方式总结


一维动态数组

“传统数组”就是前面所使用的数组,与动态内存分配相比,传统数组主要有以下几个缺点:

1) 数组的长度必须事先指定,而且只能是常量,不能是变量。比如像下面这么写就是对的:

int a[5];

而像下面这么写就是错的:

int length = 5;

int a[length];  //错误

2) 因为数组长度只能是常量,所以它的长度不能在函数运行的过程当中动态地扩充和缩小。

3) 对于数组所占内存空间程序员无法手动编程释放,只能在函数运行结束后由系统自动释放,所以在一个函数中定义的数组只能在该函数运行期间被其他函数使用。

 

malloc函数的使用

那么动态内存是怎么造出来的?在讲如何动态地把一个数组造出来之前,我们必须要先介绍 malloc 函数的使用。

malloc 是一个系统函数,它是 memory allocate 的缩写。其中memory是“内存”的意思,allocate是“分配”的意思。顾名思义 malloc 函数的功能就是“分配内存”。要调用它必须要包含头文件<stdlib.h>。它的原型为:

# include <stdlib.h>

void *malloc(unsigned long size);

malloc 函数只有一个形参,并且是整型。该函数的功能是在内存的动态存储空间即堆中分配一个长度为size的连续空间。函数的返回值是一个指向所分配内存空间起始地址的指针,类型为 void*型。

简单的理解,malloc 函数的返回值是一个地址,这个地址就是动态分配的内存空间的起始地址。如果此函数未能成功地执行,如内存空间不足,则返回空指针 NULL。

辨析

int i = 5; //静态分配

int *p = (int*)malloc(4); //动态分配

1:malloc是由程序员在堆栈动态开辟空间 
2:返回值开辟空间的首地址,但是类型是void *,需要强制类型转换 
3:分配的内存空间应该能整除类型所占的字节数 
4:包含头文件malloc.h 
5:只能用free(p)来释放p所指向的动态开辟的内存空间。 
6:对动态内存空间的操作,用*p来操作。 
7:可以用多个指针指向这个动态空间 
8:当有多个指针只向这个动态空间时,只能用free一个指针,多次重复释放要被报错 
9:可以将动态开辟的的内存指针作为函数参数

试一试:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

int main()
{
	int length, i; //length是数组的长度,i是循环变量

	scanf("%d", &length);
	int *p = (int *)malloc(20); //构造一个一维数组,长度是4字节 * 5个=20字节

	if (length > 5)
	{
		printf("长度超出了5个,需要重新申请长度。\n");
		p = (int*)realloc(p, length * 4);
	}
	for (i = 0; i < length; i++) //初始化
	{
		p[i] = i;
	}
	for (i = 0; i < length; i++) //输出
	{
		printf("%4d", p[i]);
	}
	free(p);

	system("pause");
	return 0;
}

 

实例

#include <stdio.h>
#include <time.h> //必不可少头文件:随机数
#include <stdlib.h> //必不可少头文件:动态分配空间

void GetRandomNumber(int* a, int n)
{
	srand((unsigned int)time(NULL));
	int i;
	for (i = 0; i < n; i++)
	{
		a[i] = rand() % 100;
	}
}
void show(int* a, int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
}

int main()
{
	int* a = NULL;
	int n;
	scanf("%d", &n);
	a = (int*)malloc(sizeof(int) * n);

	GetRandomNumber(a, n);
	show(a, n);

	return 0;
}

 


二维动态数组

简单实现:

//动态的二维数组(最原始实现)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h> //必不可少头文件
#include <stdlib.h> //必不可少头文件

void GetRandomNumber(int** a, int n)
{
	srand((unsigned int)time(NULL));
	int i, j;
	for (i = 0; i < n; i++)
	{
		a[i] = (int*)malloc(sizeof(int) * n); //表明每行有n个元素位置
		for (j = 0; j < n; j++)
		{
			a[i][j] = rand()%100;
		}
	}
}
void show(int** a, int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			printf("%d  ", a[i][j]);
		}
		printf("\n第%d行完毕!\n", i+1);
	}
}

int main()
{
	int n = 100;
	int** a; //申明一个二维数组指针、二维指针变量

	a = (int**)malloc(sizeof(int*) * n); //表明二维数组总共有n行

	GetRandomNumber(a, n);
	show(a, n);
	return 0;
}

逻辑严密一点:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void InitArray(char** a, int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		a[i] = (char*)malloc(sizeof(char) * n);
		if (a[i] == NULL) //如果没有判空操作,上一行代码则会发出警告:“取消对NULL指针的引用”
		{
			return;
		}
		for (j = 0; j < n; j++)
		{
			a[i][j] = 'a';
		}
	}
}
void ShowArray(char** a, int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			printf("%c ", a[i][j]);
		}
		printf("\n一行输出完了\n");
	}
}
int main()
{
	char** a;
	int n = 100;

	a = (char**)malloc(sizeof(char*) * n); //这里千万不能写为” sizeof(char) * n”!!!
	InitArray(a, n);
	ShowArray(a, n);

	return 0;
}

结果:

注意:

释放内存:

释放二维动态数组内存
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void InitArray(char** a, int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		a[i] = (char*)malloc(sizeof(char) * n);
		if (a[i] == NULL) //如果没有判空操作,上一行代码则会发出警告:“取消对NULL指针的引用”
		{
			return;
		}
		for (j = 0; j < n; j++)
		{
			a[i][j] = 'a';
		}
	}
}
void ReleaseArray(char** a, int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		free(*(a + i));
	}
}
void ShowArray(char** a, int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			printf("%c ", a[i][j]);
		}
		printf("\n一行输出完了\n");
	}
}
int main()
{
	char** a;
	int n = 100;

	a = (char**)malloc(sizeof(char*) * n);
	InitArray(a, n);
	ShowArray(a, n);
	ReleaseArray(a, n);

	return 0;
}

区分行列:

区分行列的动态二维数组
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int** a;
	int i, j;
	int row, column; //行,列
	row = 2; column = 3;
	/*
	2行3列为:
	第一行第一列	第一行第二列
	第二行第一列	第二行第二列
	*/

	a = (int**)malloc(sizeof(int*) * row);
	for (i = 0; i < row; i++)
	{
		a[i] = (int*)malloc(sizeof(int) * column);
		for (j = 0; j < column; j++)
		{
			a[i][j] = i * j;
		}
	}

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < column; j++)
		{
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
	return 0;
}
/*
输出:
0 0 0
0 1 2
*/

二维动态数组的使用方式总结

a.声明:int **a;

b.给内存:a=(int **)malloc(二维数的行数 * seizeof(int*));

      for(i=0;i<二维数组的行数;i++) 

            a[i]=(int *)malloc(每行有多少个元素 * sizeof(int));

c.即可以如常规的二维数组使用;

 

【YOLOv8实战】从零构建番茄成熟度智能检测GUI系统【附完整工程】 本文详细介绍了从零构建基于YOLOv8的番茄成熟度智能检测GUI系统的完整实战流程。内容涵盖环境搭建、数据集准备、模型训练调优,并重点讲解如何使用PyQt5开发图形界面,最终将项目打包为可执行文件,实现AI模型从训练到桌面应用落地的完整工程闭环。 阅读详情

相关推荐

2.ROS实用工具:坐标变换

本文围绕ROS坐标变换展开,介绍其在机器人系统中的关键作用,即统一不同传感器和执行器坐标系,服务数据融合等操作。基于ROS的tf库,从广播和监听TF变换两方面阐述实现过程,涵盖新建工作包、编写广播和监听代码、配置构建文件及编译等步骤。此外,介绍启动节点管理器后运行广播和监听节点的方法,并通过rqt_graph、rqt_tf_tree、tf_echo等工具可视化和获取坐标系变换信息。借助这些内容,读者不仅能掌握ROS坐标变换的实现,还能对机器人坐标变换系统的调试和理解有更深入认识 。

qq_74168740的博客 1173

动态数组的使用

Delphi动态数组的使用

lyhoo163的专栏 6118

一步一步搭建S32K14x的AutoSar项目----S32DS 代码工程的搭建

一步一步搭建S32K14X的AutoSar项目----S32DS代码工程的搭建

wo580231的博客 3487

C的动态数组的详细知识(网上收集到的大量详细知识以及个人理解的汇总)

C版本动态数组用到的函数:

weixin_44001521的博客 828

TikTok达人私信自动化:用Node.js和纯JavaScript实现WSS协议通信(附完整代码结构)

本文详细介绍了如何使用Node.js和WSS协议实现TikTok达人私信自动化系统。通过分层架构设计、WSS连接管理、消息加密策略及频率控制,开发者可以构建稳定高效的私信工具,突破平台API限制,适用于跨境电商和社交媒体运营场景。

weixin_30352645的博客 519

MacOS Intel芯片实战:Docker Compose一键部署Dify全流程解析

本文详细解析了在搭载Intel芯片的MacOS系统上,使用Docker Compose一键部署开源LLM应用开发平台Dify的全流程。内容涵盖环境准备、Docker配置与镜像加速、代码拉取与配置初始化、服务启动与问题排查,以及访问验证与初步探索,旨在帮助开发者快速在本地搭建私有化AI应用开发环境。

ik678901234的博客 618

c语言在函数中返回数组,关于C语言函数返回数组的问题

关于C语言函数返回一个数组c语言中函数不能直接返回一个数组,但是可以用其他方式实现类似功能,不过需要注意:1、该数组不能是返回函数的局部变量数组,因为局部变量数组在退出函数后会被释放。可以是全局变量,静态局部变量,动态分配内存,以及从函数参数传过来的数组地址。2、返回指针时,无法返回长度,所以需要其它方式传回数组长度,以下是几种常用的方法。1) 约定固定长度;2) 以函数参数返回数组长度;3)将长...

weixin_42365234的博客 8160

Android Jetpack 最全面试题及参考答案

要使用 WorkManager 定义一个异步任务,以下是详细步骤。首先,需要创建一个继承自 Worker 类的自定义类,这个类代表了要执行的具体任务逻辑。// 在这里编写具体的任务逻辑,比如从网络下载文件try {在上述代码中,doWork方法就是任务的核心执行逻辑所在,这里模拟了从给定的 URL 下载文件到本地的操作,若下载成功返回,若出现异常则返回。然后,在需要调度任务的地方,比如在某个 Activity 或者 Fragment 中,通过构建 WorkRequest 来安排任务执行。

大模型大数据攻城狮的专栏 1895

【C语言】动态分配一个二维数组+图解

C语言,二维数组,动态申请二维数组.

虾米Life 2972

基于Python的彩票数据爬虫:数据抓取与趋势分析

爬虫是一种用于从互联网上自动抓取信息的程序。在抓取彩票数据时,我们首先需要确定目标网站并获取其网页内容,接着提取彩票的开奖结果信息并保存。彩票数据通常是以HTML表格或列表的形式展示,爬虫可以利用Python的requests和来抓取静态网页,或使用Selenium来抓取动态页面。在本篇博客中,我们深入探讨了如何使用Python编写彩票数据爬虫,抓取并分析彩票开奖结果。通过Python爬虫技术,结合数据分析与可视化工具,我们能够全面分析历史开奖数据,揭示彩票号码的频率分布、趋势变化以及未来的可能走势。

2201_76125261的博客 1939

matlab 受约束的 Delaunay 三角剖分【2025最新版】

matlab内置调用函数实现受约束的 Delaunay 三角剖分并将结果保存为STL文件

点云侠的博客 1875

JNA —— Java调用C/C++动态库

工作所需,要使用Java调用c/c++的动态库,实现Java程序使用动态库中的函数。 搜索了一番,常用的有JNI、JNA方法。 JNI(Java Native Interface) JNA(Java Native Access) JNI需要Java和c/c++

giveaname的专栏 1万+

拉曼光谱入门:5.表面增强与共振增强

拉曼散射效应因其弱信号特性限制了传统拉曼光谱术的检测灵敏度。为克服这一局限,表面增强拉曼光谱术(SERS)和共振增强拉曼光谱术(RRS)被开发出来,显著提升了信号强度。SERS通过金属表面的电磁和化学效应放大信号,而RRS则通过匹配激发光波长与分子电子跃迁波长来增强信号。这两种技术扩大了拉曼光谱的应用范围,尤其在低浓度和微量试样分析中表现出色,尽管在实验操作和试样损伤方面存在挑战。

qq_53529450的博客 1446

C语言动态分配数组

最近在研究C语言相关的东西,遇到了一些问题,主要是关于数组内存分配的问题。我们最常用的数组分配方式就是使用 int array[] ={1,2,3,4}来分配固定长度的数组,但是当需要动态分配数组长度的时候怎么办呢?最近在使用的时候就遇到了,然后自己搜了搜相关的使用方法。 1.先介绍基本数据类型的创建方法 int array; printf(“请输入数组的长度:”); scanf("%d",&am...

WorldControl的博客 969

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

typedef、动态定义一个二维数组

一、typedef使用 1、typedef:定义一个数据类型;定义:typedef 旧类型名 新类型名(别名); typedef一般用于复杂的数据类型中,使其简单化; typedef可以这样理解:首先去掉typedef,确定是定义一个什么变量,然后加上typedef,其就由变量提升为数据类型;这样看更容易理解; 例如: typedef unsigned long long int uint64...

巨星博客 3085

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Python调用c/c++动态库(一)

因为工作需求,最近要使用python在linux环境下调用c/c++的动态库,执行动态库中的函数。这种没接触过的内容,自然首先开启百度谷歌大法。经过一番搜索,尝试使用python的ctypes模块。 一、初识 首先自然是查询文档了。附文档链接:https://docs.python.org/zh-cn/2.7/library/ctypes.html python2.7文档描述:“cty...

giveaname的专栏 2万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【C/C++】纯C实现变长数组

编写一个动态数组库可以帮助我们深入理解数据结构和内存管理,特别是在没有 C++ STL 的情况下使用 C 语言创建动态数组。我们将逐步搭建这个动态数组库(称为 Vector),并逐行解释其实现方式,让读者理解每一行代码的作用和实现细节。

2303_80346267的博客 1430

byte python 数组_Python--ctypes(数据类型详细踩坑指南)

pthon--ctypes包装C语言数据类型一. ctypes使用介绍  ctypes 是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。可使用该模块以纯 Python 形式对这些库进行封装。这篇文章主要是介绍如何使用ctypes模块对C语言编译的动态链接库要求的数据类型进行封装,主要包括以下几类:C语言中基础的数据类型(如char, int等)...

weixin_34108829的博客 1887

C语言中的复杂数据类型

目录 文章目录目录复杂数据类型结构体结构体指针和成员的引用结构体数组构建链表共用体位域枚举复杂数据类型总结 复杂数据类型 对于任何一门能够处理实际应用的编程语言,基本数据类型都是不够用的,只能存放线性数据的数组也是不够用的,例如一个学生拥有姓名、性别、年龄等内容,这样的内容必须用复杂数据类型来描述,对于高级语言来说复杂数据类型可以用类描述,对于C这样的面向过程语言,C标准提供了结构体、共用体这样的复杂数据类型来描述。 结构体 结构体这种数据类型有很多称呼,有的称关联数组,有的称为构造型数组,在结构体中可以定

jaj2003的博客 2458

objective c中的数组和简单操作(四)

holydancer原创,如需转载,请在显要位置注明: 转自holydancer的优快云专栏,原文地址:http://blog.csdn.net/holydancer/article/details/7346221 在objective c中,除了C的数组使用方法,Cocoa还为我们提供了一个NSArray类,使用该类可以简单方便的存储对象,该类同NSMutableString一样,

zhaoweixing1989的专栏 556

C语言1.用地址传递更新数组顺序,c语言的笔记

下面把我这半年来记的一些C语言的笔记贴出来。1C语言中函数参数传递是按照“值传递”进行的,即单向传递。2函数原型:函数类型 函数名(参数类型,参数类型……),可以不必加参数名,因为操作系统不检查参数名。3数组作为实参传递,型参若也是数组声明,可以第一维不指定数组大小,此时这个数组已经退化为一个指针,因此数组长度需要在参数当中接收。局部引用型参数组名的时候,其实它已经不是数组而只是一个指...

weixin_33586619的博客 463

c语言模拟模板的函数的方法

 要求用C语言(不许用C++)编写一个函数,调用这个函数可以对一个数组进行排序,这个数组可以是整型、浮点型等。函数头(返回类型、函数名、参数列表)自定。 void mySort( void* p, int len, int dataType );描述一下,首先将数组的指针传过来,因为C语言里面,任何类型的指针都可以赋值给空类型的指针,所以这个赋值完全可以通过编译;第二个参数是数组的

qunnuo的专栏 802

python ctypes 结构体数组_Python ctypes模块使用方法与心得体会

1简介ctypes是一个自Python 2.5开始引入的,Python自带的函数库。其提供了一系列与C、C++语言兼容的数据结构类与方法,可基于由C源代码编译而来的DLL动态链接库文件,进行Python程序与C程序之间的数据交换与相互调用。本文基于Python 3.6.3(64 Bit)以及MinGW GCC 6.3.0(64 Bit)。注意,在使用ctypes的过程中,Python解释器与C编译...

weixin_36227085的博客 4853

SystemVerilog与C语言交互实战:DPI-C接口数据类型映射全解析(附避坑指南)

本文深入解析SystemVerilog与C语言交互中的DPI-C接口数据类型映射,提供实战案例和避坑指南。涵盖四值类型处理、性能优化技巧及复杂数据类型操作,帮助工程师提升验证环境稳定性和仿真效率。特别关注DPI-C接口的核心机制与常见错误解决方案。

d6e7f8g9h的博客 185

C语言——动态数组的创建和使用

动态数组是相对于静态数组而言的,从“动”字可以看出它的灵活性。静态数组的长度是预先定义好的,在整个程序中,一旦给定数组大小后就无法改变。而动态数组则不然,它可以根据程序需要重新指定数组大小。动态数组的内存空间是由堆动态分配的,通过执行代码为其分配存储空间,只有程序执行到分配语句时,才为其分配存储空间。

专注于C语言编程干货分享 3万+

C语言学习笔记:动态数组

动态数组 数组是C语言中的很重要的一种构造类型,最初我们学习的都是静态数组,但是,静态数组有着自己难以改变的缺点——数组长度固定。 一般在静态数组定义后,系统就会为其分配对应长度的连续的专有内存空间,可是,我们都知道,不同的运行样例,所需要的数组长度是不一样的,为了所有样例都可以执行,一般我们会将数组长度设置为一个很大的值,比如:我一般都是借助宏定义直接声明1000,这个长度是可以满足我日常所需的。虽然这种方式,满足了一般运行的要求,但是它极大的浪费了内存。 于是我们引出了动态数组的概念,顾名思义,“动态”

jianbai_的博客 5万+
上一篇: C语言的"printf" 和 C++的"cout" 执行速度,那个更快?
下一篇: 在C++中,用“new”自定义动态数组
ALGO阿狗
博客等级 码龄9年 64粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值