目录

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:指针和数组相关推荐

  1. C程序设计语言--第五章:指针与数组

    为什么80%的码农都做不了架构师?>>>    指针是一种保存变量地址的变量. 5.1 指针与地址 通常的机器都有一系列连续编号或编址的存储单元,这些存储单元可以单个进行操纵,也可以 ...

  2. 《C程序设计语言》笔记 (五) 指针与数组

    5.1 指针与地址 指针是一种保存变量地址的变量ANSI C使用类型void*(指向void的指针)代替char *作为通用指针的类型一元运算符&可用于取一个对象的地址: p = &c ...

  3. C程序设计语言现代方法08:数组

    目录 1. C语言中的变量 2. 一维数组 2.1 数组的声明 2.2 数组初始化 2.3 对数组使用sizeof运算符 3. 多维数组 4. 常量数组 4. C语言数组类型 4.1 数组类型 4.2 ...

  4. C程序设计语言现代方法13:字符串

    目录 1. 字符串字面量 1.1 定义 1.2 字符串字面量包含转义序列 1.3 延续字符串字面量 1.3.1 使用续行符 1.3.2 仅用空白字符分割字符串字面量 1.4 存储字符串字面量 1.5 ...

  5. java的字符串指针数组,C语言字符串中的指针与数组

    先说一下字符串字面量(字符串常量):双引号中的字符和编译器自动加入末尾的\0字符,都作为字符串储存在内存中.字符串常量属于静态存储类别,说明如果在函数中使用字符串常量,该字符串只会储存一次,在整个程序 ...

  6. 【牛客网】C语言入门 - CC4 利用指针遍历数组

    题目描述 题目链接:利用指针遍历数组 描述 键盘随机输入 6 个整数,将这些数据保存到数组中,利用指针遍历数组中的元素并打印. 输入描述: 键盘随机输入 6 个整数 输出描述: 输出数组中的所有元素, ...

  7. 【C语言】小妹不懂指针和数组的关系?那就安排指针数组关系详解

    目录 前言 一.什么是数组 二.什么是指针 三.指针变量的大小 四.数组和指针的关系 五.指针变量的自增自减运算 六.两个参数确定一个数组 七.字符型指针和字符型数组 总结 写在最后 前言 前段时间整 ...

  8. C语言结构体中指针指向数组,指向结构体类型数组的指针的使用

    指向结构体类型数组的指针的使用 定义一个结构体类型数组,其数组名是数组的首地址,下面是关于指向结构体类型数组的指针的使用具体介绍,欢迎阅读! 定义结构体类型的指针,既可以指向数组的元素,也可以指向数组 ...

  9. C程序设计语言现代方法17:指针的高级应用

    目录 1. 动态存储分配 1.1 malloc函数 1.2 calloc函数 1.3 realloc函数 1.4 free函数 2. 空指针NULL解析 2.1 NULL的定义形式 2.2 程序如何知 ...

最新文章

  1. html 里运行php文件,如何在HTML文件中运行PHP脚本
  2. 用c语言实现单链表的初始化,建表,查找,求长度,插入,删除等操作,【YTU+2430+C语言习题+链表建立+插入+删除+输(5)...
  3. CodeForces - 346A Alice and Bob(数论+博弈)
  4. 作者:张飞波,华侨大学信息管理系本科在读。
  5. e会学中C语言课程考试答案,管理信息系统期末考试A试卷答案卷
  6. 两栏布局的5中实现方式
  7. MySQL优化详解(四)——MySQL缓存设置
  8. dubbo源码解析-spi(一)
  9. keyshot可以打开mtl文件吗_KeyShot:bip文件是什么?bip文件用什么打开?
  10. 树莓派入门(二)—— 系统安装前格式化TF卡
  11. eeepc linux 窗口管理器,EeePC安装Windows 7全教程 全机型适用
  12. 大陆高校毕业IEEE fellow榜单
  13. c++如何输入一个不定长的字符串数组
  14. OpenMP 快速入门
  15. Qlikview Data Modeling---创建一个Key/Link Table
  16. U8 EAI实现XML的生成
  17. 了解一下chirp,扫频信号的生成
  18. ICC2 CTS STEP
  19. 什么是域名劫持和域名污染
  20. 拓嘉辰丰电商:拼多多“快团团”买赠常见玩法

热门文章

  1. php打造自己的喜马拉雅,打造自己的私人知识宝库利器——mybase 7.3.5
  2. Trees on the level UVA - 122 (二叉树的层次遍历)
  3. java类的加载顺序题目_Java 类的加载顺序(题)
  4. 把ct图像像素值转化为_CT爱好者的点点滴滴
  5. mysql桦仔_Microsoft SQL Server 2005技术内幕:T-SQL查询笔记
  6. 内存泄漏的原因及解决办法_内存泄漏的场景和解决办法
  7. Linux kms 模式设置,linux – 使用KMS设置控制台视频分辨率
  8. matlab模式识别实验二,模式识别实验二
  9. springboot启动图标_SpringBoot基础教程
  10. 为什么c++文件只能执行一次_numba从入门到精通(1)—为什么numba能够加速