当前课程知识点:C语言程序设计 > 第9章 指针 > 9.5 指向二维数组的指针变量(下) > 指向二维数组的指针变量(下)
同学们好
上节课中我们和同学们探讨了
指针与二维数组的关系
和大家一起研究了行指针
这节课我们将
和大家继续讨论
二维数组与指针的关系
本节内容复杂
表达式等价形式众多
同学们要多思考
多练习
以便于掌握指针的精髓
大家一定要记住*(a+i)和a[i] 等价的
有必要对a[i]的性质作进一步说明
a[i]从形式上看是a数组中
第i个元素
如果a是一维数组名
则a[i]代表a数组第i个元素
所占的内存单元的内容
一维数组的元素a[i]是有物理地址的
是占内存单元的
但如果a是二维数组
则a[i]是代表一维数组名
它只是一个地址
因为一维数组名只是一个指针常量
所以这里的a[i]也是一个地址值
所以和它等价的a
a+i
a[i]
*(a+i)
*(a+i)+j
a[i]+j是地址a、a+i是行地址
称为行指针
而a[i]作为数组的首地址
是数组第一个元素的地址
所以a[i]
*(a+i)
*(a+i)+j
a[i]+j是元素的地址
称之为列指针
对于元素的地址我们可以做取内容运算
取该元素地址所对应的内存单元的内容
*(a[i]+j)和*(*(a+i)+j)
就是二维数组元素a[i][j]的值
再一次强调
二维数组名(如a)是指向行的
因此a+1中的1
代表一行中全部元素
一维数组名如a[0]
a[1]是指向列元素的
a[0]+1中的1
从数组名对应地址偏移一个元素
是指向列的
在指向行的指针前面加一个*
就转换为指向列的指针
例如a和a+1是指向行的指针
在它们前面加一个*就是*a和*(a+1)
它们就成为指向列的指针
等价于a[0]和a[1]
分别指向a数组0行0列的元素和1行0列的元素
反之
在指向列的指针前面加取缔值&
就成为指向行的指针
例如a[0]是指向0行0列元素的指针
在它前面加一个&
得&a[0]
由于a[0]与*(a+0)等价
因此&a[0]与&*(a+0)等价
由于&
*互为逆运算
也就是&a[0]与a等价
它指向二维数组的0行
也就是一维数组数组名的&运算为行地址
不要把&a[i]简单地理解为a[i]单元的物理地址
因为并不存在a这样一个实际的变量
它只是一种地址的计算方法
能得到第0行的首地址
a和*a的值是一样的
但它们的含义是不同的
&a[0]或a+i指向行
而a[i]或*(a+i)指向列
当列下标为0时
&a[i]和a[i](即a[i]+0)值相等
即它们具有同一地址值
但应注意它们所指向的对象是不同的
*(a+i)只是a[i]的另一种表示形式
不要简单地认为是
a+i所指单元中的内容
在一维数组中a+i所指的是
一个数组元素的存储单元的地址
*(a+i)
指的是一个数组元素的存储单元的数据内容
在二维数组中
a+i=a[i]=*(a+i)=&ai=&a[i][0]
即它们的地址值是相等的
含义却不相同
请同学们任细琢磨其概念
下面我们对二维数组与指针进行总结
对二维数组 int a[3][4]
有a二维数组的首地址
即第0行的首地址为行指针
a+i第i行的首地址
是第i行的行指针
由于a+i与&a[i]等价
所以&a[i]也是行指针
a[i] 与 *(a+i)等价
二维数组中第一维的数组名
可以写成a[i]+0
和*(a+i)+0第i行第0列的元素地址
是列指针
而a[i]+j 与*(a+i)+j第i行第j列的元素地址
他们与&a[i][j]等价是i行
j列元素的地址
而*(a[i]+j)与 *(*(a+i)+j) 和a[i][j]等价
是i行
j列元素的数据内容
下面我们通过表格方式对二维数组
与指针进行总结
a是二维数组名
二维数组的首地址
它等价于a+0
是第0行的行地址
是行指针
a[0]
与*(a+0)
*a
*(a+0)+0等价是二维数组中
第一维的数组名
是第一维数组首元素的地址
即第0行第0列元素地址
即&a[0][0]
a+1
是行指针
代表a这个行指针下移一行
是第一行的地址
a[1]
*(a+1)
*(a+1)+0第一维数组首元素的地址
即第1行第0列元素地址
即&a[1][0]
而 a[1]+2
*(a+1)+2
&a[1][2]是
从数组a[1]偏移两个元素的元素地址
即第1行第2列元素地址&a[1][2]
而*(a[1]+2)
*(*(a+1)+2)
a[1][2]这几个表达式等价
是求这几个元素地址的*运算
即取内容运算
是第1行第2列元素值
这一节中我们和同学们探讨了
指针与二维数组的关系
和大家一起研究了行指针
列指针
元素的地址
以及元素的内容
本节内容复杂
表达式等价形式众多
同学们要多思考
多练习
同学们
我们下次课再见
-计算思维与计算机
--计算思维与计算机
--计算思维与计算机
--计算思维和计算机
-2.1 程序设计语言的发展及其特点和应用
--程序设计语言的特点及发展
- 2.2 C语言程序的基本结构及编制C语言程序的基本步骤
--C语言程序的结构和编制步骤
-3.1 C语言的数据类型
--C语言的数据类型
--C语言的数据类型
-3.2 常量
--常量
--常量
-3.3 什么是变量
--什么是变量
--什么是变量
-3.4 如何进行算术运算
--如何进行算术运算
--如何进行算术运算
-3.5 赋值运算符和逗号运算符
--赋值运算符和逗号运算符
-3.6 数据类型转换
--数据类型转换
--数据类型转换
-4.1 格式化输出printf
--格式化输出
-4.2 格式化输入scanf及字符数据的非格式化输入输出
--格式化输入
-5.1 关系运算符和关系表达式
--关系运算符和关系表达式
-5.2 逻辑运算符和逻辑表达式
--逻辑运算符和逻辑表达式
-5.3 条件运算符和条件表达式
--条件运算符和条件表达式
-5.4 if语句
--if语句
--if语句
-5.5 switch语句
--switch语句
--switch语句
-6.1 while语句
--while语句
--while语句
--do-while语句
-6.2 for语句
--for语句
--for语句
-6.3 循环的嵌套
--循环的嵌套
--循环的嵌套
-6.4 break语句和continue语句
--break和continue语句
-7.1 一维数组的定义和引用
--一维数组的定义和引用
-7.2 一维数组的赋值
--一维数组的赋值
--一维数组的赋值
-7.3 二维数组的定义和引用
--二维数组的定义和引用
-7.4 二维数组的赋值
--二维数组的赋值
--二维数组的赋值
-7.5 字符串的本质
--字符串的本质
--字符串的本质
-7.6 字符串操作的常用函数
--字符串常用函数
-7.7 字符串数组
--字符串数组
--字符串数组
-8.1 函数概述
--函数概述
--函数概述
-8.2 有参函数
--有参函数
--有参函数
-8.3 函数参数的传递方式
--函数参数的传递方式
-8.4 变量的作用域和生存期
--变量的作用域和生存期
-8.5 变量的存储类型
--变量的存储类型
--变量的存储类型
-8.6 函数的嵌套和递归调用
--函数的嵌套和递归调用
-8.7 函数的作用域与封装
--函数的作用域与封装
-9.1 指针变量的概念(上)
--指针变量的概念(上)
-9.2 指针变量的概念(下)
--指针变量的概念(下)
-9.3 指向一维数组的指针变量
--指向一维数组的指针变量
-9.4 指向二维数组的指针变量(上)
--指向二维数组的指针变量(上)
-9.5 指向二维数组的指针变量(下)
--指向二维数组的指针变量(下)
-9.6 动态内存分配
--动态内存分配
--动态内存分配
-10.1 编译预处理
--编译预处理
-11.1 用户自己建立数据类型
--用户自己建立数据类型
-11.2 定义结构体类型变量
--定义结构体类型变量
-11.3 结构体变量的引用与初始化
-11.4 结构体数组
--结构体数组
--结构体数组
-11.5 指向结构体类型数据的指针
--指向结构体类型数据的指针
-12.1 文件的基本概念和文件指针
--文件的基本概念和文件指针
-12,2 文件的打开和关闭
--文件的打开和关闭
--文件的打开和关闭
-12.3 文本文件读写
--文本文件读写
--文本文件读写
-12.4 二进制文件读写
--二进制文件读写
--二进制文件读写