C程序设计语言现代方法12:指针和数组
目录
1. 指针的算术运算
1.1 概述
1.2 C语言支持的算术运算类型
2. 指针的比较
3. 指针用于数组处理
4. 数组名与指针
4.1 用数组名作指针
4.2 数组取下标操作
4.3 惯用法
4.4 数组型实际参数
4.5 用指针作数组名
5. 指针和多维数组
5.1 正确理解二维数组的数组名
5.1.1 数组名可以被解释为指向数组第一个元素的指针
5.1.2 如果p指向对象x,那么*p就是对象x
5.1.3 如果x 是对象,那么&x得到指向该对象的指针
5.1.4 指针的算术计算以其指向的对象类型为单位
5.2 二维数组的降维处理
1. 指针的算术运算
1.1 概述
当指针指向数组元素时,C语言允许对指针进行算术运算(加法和减法)。通过这种运算可以用指针代替数组下标对数组进行访问
1.2 C语言支持的算术运算类型
C语言只支持3种格式的指针算术运算
① 指针加上整数
p 指向a[i],p + j 指向a[i + j]
② 指针减去整数
p 指向a[i],p - j 指向a[i - j]
③ 两个指针相减
当两个指针相减时,结果为指针之间的距离(用数组元素的个数来度量)
显然,只有两个指针指向同一个数组时,把他们相减才有意义
说明:这里需要强调,C语言只支持这3种运算,其余均报错。请看如下示例,
由于不能将两个指针相加,上述方法是不能取得数组中间位置元素的。需要做如下改进,
2. 指针的比较
只有在两个指针指向同一数组时,用关系运算符进行的指针比较才有意义,一般用于for循环遍历数组时
3. 指针用于数组处理
在用指针处理数组元素的语句中经常组合使用*(间接寻址)运算符和++运算符
表达式 |
含义 |
*p++ 或 *(p++) |
自增前表达式的值是*p,以后再自增p |
(*p)++ |
自增前表达式的值是*p,以后再自增*p |
*++p 或 *(++p) |
先自增p,自增后表达式的值是*p |
++*p 或 ++(*p) |
先自增*p,自增后表达式的值是*p |
4. 数组名与指针
4.1 用数组名作指针
可以用数组名作为指向数组第一个元素的指针
说明1:数组名被解释为指针常量,本质是因为系统没有为数组名分配存储空间。所以如下的代码是错误的,
int a[10];
++a; // 错误!!!
说明2:从技术上说,数组的名字不是指针,C语言编译器会在需要的时候(表达式中的数组名)把数组名转换为指针
区别示例:对数组名用sizeof运算符和对指针用sizeof运算符
4.2 数组取下标操作
通常情况下,a + i 等同于&a[i],*(a + i)等价于a[i]
说明:数组的取下标操作可以看成是指针算术运算的一种形式,所以a[i] 和i[a] 是一样的
// 中间转换,像普通加法一样,指针和整数相加也是可交换的
a[i] <---> *(a + i) <---> *(i + a) <---> i[a]
4.3 惯用法
for (p = a; p < a + N; ++p)sum += *p;
4.4 数组型实际参数
数组型实际参数的关键是没有复制数组本身
① 给函数传递数组所需的时间与数组的大小无关(因为只传递了地址值)
② 可以把数组型形式参数声明为指针
int find_largest(int a[], int n);
int find_largest(int *a, int n);
特别注意:对于形式参数,声明为数组跟声明为指针是一样的,但是对变量而言,声明为数组跟声明为指针是不同的,示例如下,
int a[10];
int *a;
③ 可以给形式参数为数组的函数传递数组的"片段",所谓片段是指连续的数组元素组成的序列。也就是说,在find_largest函数中,第一个参数指定的是要处理的数组元素的起始地址,第二个参数指定的是要处理的数组元素个数
4.5 用指针作数组名
int a[10];
int *p = a;p[1] = 0;
本质:数组取下标只是一种地址计算方式
5. 指针和多维数组
5.1 正确理解二维数组的数组名
设有int a[NUM_ROWS][NUM_COLS];
我们结合上一章节中总结的指针变量4句圣经来解释二维数组的数组名
5.1.1 数组名可以被解释为指向数组第一个元素的指针
二维数组的元素是一维数组,所以二维数组名指向二维数组的第一行。其指针基类型为int (*)[NUM_COLS],在对其进行算术运算时,单位为一行
5.1.2 如果p指向对象x,那么*p就是对象x
因为二维数组的数组名a 指向其中的第一个一维数组,即指向第一行。所以*a 就是第一行这个一维数组,又因为一位数组名解释为指向其第一个元素的指针,所以*a 的类型为int *。考虑到*(a + i) 和a[i] 都是等价的地址计算方式,所以*(a + i) 和a[i] 均表示第i 行一维数组,类型均为int *
实验时间:为什么说*a 就是一维数组而不是一个简单的指针变量?
我们通过sizeof 运算符作用于数组名和指针变量时的不同行为来验证
sizeof(*a) 的结果是12 而不是4,正说明*a 表示的是一个一维数组名,而不是一个简单指针
5.1.3 如果x 是对象,那么&x得到指向该对象的指针
因为*(a + i) 和a[i] 均表示第i 行一维数组,所以&*(a + i) 和&a[i] 均为指向第i 行一维数组的指针,其类型为int (*) [NUM_COL]
5.1.4 指针的算术计算以其指向的对象类型为单位
a:指向二维数组的第一行一维数组,类型int (*)[NUM_COLS]
a[0] 或*a:指向第一行一维数组的第一个元素,类型为int *
在进行算术计算时, a + 1 越过一行,而a[0] + 1 越过一个int 型数据
5.2 二维数组的降维处理
处理一维数组的函数也可以处理二维数组的一行,进而扩展了这类函数的使用范围
设有int find_largest(int *a, int n)函数,用于求得一维数组中的最大元素,如果想求二维数组中的最大元素,可做如下调用,
find_largest(*a, NUM_ROWS * NUM_COLS);
本质:*a指针类型为int *
C程序设计语言现代方法12:指针和数组相关推荐
- C程序设计语言--第五章:指针与数组
为什么80%的码农都做不了架构师?>>> 指针是一种保存变量地址的变量. 5.1 指针与地址 通常的机器都有一系列连续编号或编址的存储单元,这些存储单元可以单个进行操纵,也可以 ...
- 《C程序设计语言》笔记 (五) 指针与数组
5.1 指针与地址 指针是一种保存变量地址的变量ANSI C使用类型void*(指向void的指针)代替char *作为通用指针的类型一元运算符&可用于取一个对象的地址: p = &c ...
- C程序设计语言现代方法08:数组
目录 1. C语言中的变量 2. 一维数组 2.1 数组的声明 2.2 数组初始化 2.3 对数组使用sizeof运算符 3. 多维数组 4. 常量数组 4. C语言数组类型 4.1 数组类型 4.2 ...
- C程序设计语言现代方法13:字符串
目录 1. 字符串字面量 1.1 定义 1.2 字符串字面量包含转义序列 1.3 延续字符串字面量 1.3.1 使用续行符 1.3.2 仅用空白字符分割字符串字面量 1.4 存储字符串字面量 1.5 ...
- java的字符串指针数组,C语言字符串中的指针与数组
先说一下字符串字面量(字符串常量):双引号中的字符和编译器自动加入末尾的\0字符,都作为字符串储存在内存中.字符串常量属于静态存储类别,说明如果在函数中使用字符串常量,该字符串只会储存一次,在整个程序 ...
- 【牛客网】C语言入门 - CC4 利用指针遍历数组
题目描述 题目链接:利用指针遍历数组 描述 键盘随机输入 6 个整数,将这些数据保存到数组中,利用指针遍历数组中的元素并打印. 输入描述: 键盘随机输入 6 个整数 输出描述: 输出数组中的所有元素, ...
- 【C语言】小妹不懂指针和数组的关系?那就安排指针数组关系详解
目录 前言 一.什么是数组 二.什么是指针 三.指针变量的大小 四.数组和指针的关系 五.指针变量的自增自减运算 六.两个参数确定一个数组 七.字符型指针和字符型数组 总结 写在最后 前言 前段时间整 ...
- C语言结构体中指针指向数组,指向结构体类型数组的指针的使用
指向结构体类型数组的指针的使用 定义一个结构体类型数组,其数组名是数组的首地址,下面是关于指向结构体类型数组的指针的使用具体介绍,欢迎阅读! 定义结构体类型的指针,既可以指向数组的元素,也可以指向数组 ...
- C程序设计语言现代方法17:指针的高级应用
目录 1. 动态存储分配 1.1 malloc函数 1.2 calloc函数 1.3 realloc函数 1.4 free函数 2. 空指针NULL解析 2.1 NULL的定义形式 2.2 程序如何知 ...
最新文章
- html 里运行php文件,如何在HTML文件中运行PHP脚本
- 用c语言实现单链表的初始化,建表,查找,求长度,插入,删除等操作,【YTU+2430+C语言习题+链表建立+插入+删除+输(5)...
- CodeForces - 346A Alice and Bob(数论+博弈)
- 作者:张飞波,华侨大学信息管理系本科在读。
- e会学中C语言课程考试答案,管理信息系统期末考试A试卷答案卷
- 两栏布局的5中实现方式
- MySQL优化详解(四)——MySQL缓存设置
- dubbo源码解析-spi(一)
- keyshot可以打开mtl文件吗_KeyShot:bip文件是什么?bip文件用什么打开?
- 树莓派入门(二)—— 系统安装前格式化TF卡
- eeepc linux 窗口管理器,EeePC安装Windows 7全教程 全机型适用
- 大陆高校毕业IEEE fellow榜单
- c++如何输入一个不定长的字符串数组
- OpenMP 快速入门
- Qlikview Data Modeling---创建一个Key/Link Table
- U8 EAI实现XML的生成
- 了解一下chirp,扫频信号的生成
- ICC2 CTS STEP
- 什么是域名劫持和域名污染
- 拓嘉辰丰电商:拼多多“快团团”买赠常见玩法
热门文章
- php打造自己的喜马拉雅,打造自己的私人知识宝库利器——mybase 7.3.5
- Trees on the level UVA - 122 (二叉树的层次遍历)
- java类的加载顺序题目_Java 类的加载顺序(题)
- 把ct图像像素值转化为_CT爱好者的点点滴滴
- mysql桦仔_Microsoft SQL Server 2005技术内幕:T-SQL查询笔记
- 内存泄漏的原因及解决办法_内存泄漏的场景和解决办法
- Linux kms 模式设置,linux – 使用KMS设置控制台视频分辨率
- matlab模式识别实验二,模式识别实验二
- springboot启动图标_SpringBoot基础教程
- 为什么c++文件只能执行一次_numba从入门到精通(1)—为什么numba能够加速