当前课程知识点:高级语言程序设计 >  数组 >  5.4 二维数组的定义和初始化 >  二维数组的定义和初始化

返回《高级语言程序设计》慕课在线视频课程列表

二维数组的定义和初始化在线视频

二维数组的定义和初始化

下一节:二维数组的使用

返回《高级语言程序设计》慕课在线视频列表

二维数组的定义和初始化课程教案、知识点、字幕

大家好

从本节课开始我们来学习

二维数组的相关知识

在前面我们学习了一维数组的相关知识

下面我们来看一看二维数组的定义和初始化

我们先来看看二维数组定义的一般形式

和前面的一维数组类似

开始是类型名 空格

后面是标识符

这里的标识符充当二维数组

标识符后面有两个中括号

中括号里面是两个整型常量表达式

比如 我们看个例子

int a[3][4];

和前面学习的一维数组的定义相比

我们发现二维数组的定义

多了一个中括号

有两个中括号

所以它是二维数组

一个中括号意味着有一个下标

两个中括号那就有两个下标

我们需要两个下标

才能确定二维组中的一个元素

定义开始时的类型名和一维数组一样

指的是数组元素的类型

也称数组类型

那么标识符a在这里充当了二维数组名

因为它后面跟了两个中括号

所以是二维数组

第一个中括号里面的整型值3

那么就定义了第一个下标

有3种变化

由于C语言的下标是从0开始

所以第一个下标的可以是0

可以是1

可以是2

那么第二个中括号里面的值4

那么和前面的第一个中括号里面的值3类似

它定义了第二个下标

允许有4种变化

也就是0 1 2 3

所以上面举例的

二维数组a

那么就有12个元素

分别是a[0][0] a[0][1] a[0][2] a[0][3]

a[1][0] a[1][1] a[1][2] a[1][3]

a[2][0] a[2][1] a[2][2] a[2][3]

相当于12个int类型的变量

每一个我们称为数组中的一个元素

这些元素在内存中的存储示意图如下

二维数组中的第一个下标也称行下标

第二个下标也称列下标

这是为什么呢

因为二维数组它对应的一个矩阵

比如上面的二维数组对应下面的矩阵

那么观察到矩阵中

每一行元素的第一个下标值

都是一样的

比如第一行第一个下标全是0

第二行第一个下标全是1

第三行第一个下标全是2

因此第一个下标确定的元素

在矩阵中的行

所以我们把二维数组中的第一个下标

称为行下标

类似的

因为二维数组中的第二个下标

确定了元素在矩阵中的列

所以我们称为列下标

对应数组a

对照一下数组a对应的矩阵和存储示意图

我们会发现

先存储数组a的第一行

即行下标为0的元素

然后是第二行

再是第三行

在每一行中

先是第一列

然后是第二列

第三列

第四列

这种存储二维数组的方法

我们称为“先行后列”的存储数组方法

大多数语言是按这种方法来存储数组的

但也有些语言

是按照“先列后行”的方法来存储

比如PASCAL语言

那么注意到数组中的元素类型相同

也就是定义时开始的类型名表示的类型

也就是说数组a

每一个元素占据内存的字节数

是sizeof(int)

观察我们这个存储示意图

和我们前面讲的知识

我们知道数组a中的元素是连续存放的

而且它是按先行后列的顺序来存放的

所以只要知道了下标i和下标j

也就是行下标和列下标

那么a[i][j]它的地址应该为

第一个元素的地址a[0][0]的地址

加上它前面的元素的个数

也就是行下标i

乘以每一行

元素的个数是4个

i乘以4

再加j

j是a[i][j]的列下标

i是a[i][j]的行下标

即第i+1行

前面有j个元素

因为列下标也是从0开始的

所以是i*4+j

前面有这么多个元素

再乘上每一个元素占据的字节数sizeof(int)

那么就是a[i][j]的地址

我们来验证看一看是不是正确

显然数组中第一个元素的地址

就是a[0][0]的地址

那么a[0][1]的地址

就是&a[0][0]+sizeof(int)

那么放到上面的公式里面

由于a[0][1]

i的值是0

j的值是1

那就是a[0][0]的地址加上圆括号里面0乘以4加1

这个结果再乘以sizeof(int)

这是符合公式的

我们再来看看一个元素

a[2][3]的地址看看是不是符合公式

a[2][3]与我们这个连续存放开始的第一个元素a[0][0]

相隔有多少个元素呢

我们从对应的矩阵里面来数一数

行下标第一行

行下标为0的有4个

那么行下标为1的同样有4个

行下标为2的

也就是与a[2][3]是同一行前面的有3个

也就是说相隔有2个4个

和1个3这么多个元素

所以

&a[2][3]=&a[0][0]+(2*4+3)sizeof(int)

这是符合公式的

那么进一步我们把它推广到一般情形

假定有一个宏定义

#define N 3

N在这里代表多少行

行数

#define M 4

M在这里是列数

那么如果元素类型用type表示

那这个二维数组是

type a[N][M];

那么&a[i][j]的地址显然就是

&a[0][0]+(i*M+j)*sizeof(type)

圆括号里面是元素的类型

数组中每个元素是占据的字节数

推出这个公式有什么意义呢

它的意义就在于

&a[0][0]的地址是第一个元素的地址

那么只要我们知道第一个元素的地址

再知道了每一个元素它的行下标和列下标

那么我们就可以计算出a[i][j]的地址

因此&a[0][0]的地址

也是数组中这块连续存储空间的首地址

我们只要知道了a[0][0]的地址

知道了数组中元素的下标

那么我们可以计算出任何一个数组元素的地址

知道了元素的地址

我们就可以访问这个元素

这正是数组元素的引用里面

为什么我们是数组名加下标

就可以了引用数组元素的原因

因为在C语言中

数组名就是数组的首地址

数组名就是我们第一个元素的地址

是数组的首地址

那么在这里要注意

数组名和一般的地址不一样

它是一个常量

数组名是数组的首地址

而且是一个常量

那么下面我们看一看

二维数组的引用

我们如何来引用二维数组中的元素

二维数组的引用是这样的

数组名[行下标值][列下标值]

第一个中括号里面要放行下标值

第二个中括号里面要放列下标值

注意行下标和列下标

可以是由任何整型表达式充当

下标值是从0开始到定义的最大允许值

这个定义的最大允许值怎么计算呢

举个例子

比如 int a[3][4]

那么行下标的最大允许值就是2

比我们定义的这个3要小一个

因为是从0开始的

那么从0到2恰好是3个

同样列下标的最大允许值

就是比定义的最大允许值要小一个

在这里就是3

那么这是单个的引用二维数组中的元素

如果要批处理引用二维数组中的元素

也就是对二维数组中的元素每一个都访问到

或者说大多数都访问到

我们可以如下定义

如果定义是这样的

int a[N][M],i,j;

for(i=0;i

for(j=0;j

访问a[i][j]

这是下标从小到大

那么下标从大到小

它的一般方法是这样的

同样是for循环的三层嵌套

for(i=N-1;i>=0;i--)

for(j=M-1;j>=0;j--)

来访问a[i][j]

这样就能给我们定义的二维数组

每一个元素都访问到

这是二维数组的引用

下面我们看一看二维数组的初始化

二维数组的初始化可以分为

分行初始化和不分行的初始化这两种情形

下面我们先看一下分行的初始化

我们看个例子

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

注意元素值之间用逗号分隔

花括号和花括号之间也要用逗号分隔

这是分行的全部初始化

那么这里花括号里面的花括号

实际上就指明了行数

因此在这种分行的全部初始化的时候

定义时的行数可以省略

比如上面刚才的定义语句可以写成

int a[][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

在跟刚才的初始化

这是分行的全部初始化

分行的初始化也可以是部分初始化

我们再看一个例子

比如int yh[][3]={{1},{1,1},{1,2,1}};

那么这里定义的行数也可以省略

定义的第一个常量的表达式的值也可以省

因为花括号里面花括号的个数

就确定了它的行数

好这是分行的初始化

再看不分行的初始化

比如说int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

这就是一种不分行的初始化

而且是全部初始化

因为里面给的12个值

恰好对应了12个元素

这种不分行的初始化

像这种每一个元素的值都给出来了

我们叫不分行的全部初始化

这个时候定义的时候

行数值也可以省略

比如刚才的定义也可以写成

int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12};

因为花括号里面的12个值

这个值的个数除以我们定义时候的列数

那么恰好是等于3

与我们给定的行数是一致的

所以可以省略

与一维数组的分行的部分初始化一样

我们这个二维数组分行的初始化

也可以只给部分值

比如int a[3][4]={1,1,1,1,1}

那么在这种情况下

这个定义数组a的中括号里面的行数3不能省略

按照先行后列的排序

这5个1

第一个1送给了二维数组中

第一行的第一个元素

第二个1送给了第一行的第二个元素

也就是它给的先行后列排序里面的前面五个元素

也就是a[0][0] a[0][1] a[0][2] a[0][3] a[1][0]

那么把刚才的初始化的知识总结一下

分行初始化和不分行的全部初始化时

在定义二维数组行数的时候

这个指定可以省略

那么不分行的部分初始化

那么定义时候指定行数不能省略

这就是二维数组初始化的内容

好关于二维数组的定义

二维数组元素的引用

二维数组的初始化我们就讲完了

本节课内容讲完了谢谢大家

高级语言程序设计课程列表:

程序设计和C语言

-1.1 计算机程序和计算机语言

--计算机程序和计算机语言

--致敬先辈:伟大的C语言之父——丹尼斯·里奇 程序员

-1.2 C程序的构成

--C程序的构成

--当前主流程序设计语言各自都有什么优势?

-1.3 C语言编辑、编译、运行(VC++2010学习版)

--C语言编辑、编译、运行(VC++2010学习版)

-练习题

顺序结构程序设计

-2.1 变量的定义和使用

--变量的定义和使用

-2.2 数据类型

--数据类型简介

--整型数据

--实型数据

-2.3 格式输出和格式输入

--格式输出printf函数

--格式输入scanf函数

--单个字符的输入输出

-2.4 运算符和表达式

--运算符和表达式

-2.5 结构化程序设计入门

--结构化程序设计入门

-练习题

选择结构程序设计

-3.1 为什么要用选择结构解决问题

--为什么要用选择结构解决问题

-3.2 如何正确表示选择结构中的条件

--如何正确表示选择结构中的条件

-3.3 用if语句及if语句嵌套实现选择结构

--用if语句及if语句嵌套实现选择结构

-3.4 用switch语句实现选择结构

--用switch语句实现选择结构

-练习

循环结构程序设计

-4.1 循环的引入

-- 为什么要用循环结构解决问题

-4.1 循环的引入--作业

-4.2 用while语句实现循环

--用while语句实现循环

-4.3 用do-while语句实现循环

-- 用do-while语句实现循环

-4.4 用for语句实现循环

-- 用for语句实现循环

-4.4 用for语句实现循环--作业

-4.5 何时需要用循环的嵌套

--何时需要用循环的嵌套

-4.6 如何提前终止循环和提前结束本次循环

--如何提前终止循环和提前结束本次循环

-习题--作业

数组

-5.1 数组类型的引入

--数组类型的引入

-5.2 一维数组的定义和初始化

--一维数组的定义和初始化

-5.3 一维数组的使用

--一维数组的使用

-5.4 二维数组的定义和初始化

--二维数组的定义和初始化

-5.5 二维数组的使用

--二维数组的使用

-习题--作业

指针

-6.1 什么是指针

--什么是指针

-6.2 指针类型及相关概念

--指针类型及相关概念

-6.3 指针变量的定义、赋值与使用

--指针变量的定义、赋值与使用

-6.4 指针的运算

--指针的运算

-6.5 指针与一维数组

--指针与一维数组

-6.6 指针的指针

--指针的指针

-6.7 指针与二维数组

--指针与二维数组

-习题--作业

函数

-7.1 为什么要自定义函数

--为什么要自定义函数

-7.2 函数的定义

--函数的定义

-7.3 函数的调用

--函数的调用

-7.4 函数参数的传递

--函数参数的传递

-7.5 函数的嵌套调用和递归调用

--函数的嵌套调用和递归调用

-7.6 变量的作用域和存储类型

--变量的作用域和存储类型

-习题--作业

字符串

-8.1 字符串的存储及输入输出

--字符串的存储及输入输出

-8.2 系统字符串处理函数

--系统字符串处理函数

-8.3 自定义字符串处理函数

--自定义字符串处理函数

-习题--作业

结构体和共用体

-9.1 结构体类型的定义

--结构体类型的定义

-9.2 结构体变量及指针变量的定义及使用

--结构体类型变量和指针变量的定义和使用

-9.3 结构体变量和指针变量作函数的参数

--用结构体变量和指向结构体的指针作函数参数

-9.4 结构体数组的定义和使用

--结构体数组的定义和使用

-9.5 共用体类型和枚举类型

--共用体和枚举类型

-习题--作业

动态内存分配

-动态内存分配--习题

文件

-习题--作业

二维数组的定义和初始化笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。