C指针和数组的关系详解
1.C中数组和指针的关系
对于任意类型的数组arr,对于同类型的指针类型parr(确切一点,可以假设类型为int,即int arr[], *parr
)。它们之间有如下"内幕":
1.数组的名称arr本身就是一个指针,这个指针指向数组的第一个元素
2.因为名称arr本身是指针,所以可以直接赋值给同类型的指针parr:parr = arr
,这使得parr也指向数组的第一个元素,所以这个赋值过程等价于parr = &arr[0]
3.指针和数组名在效果上是等价的。它们的区别在于:指针是变量。指针变量可以参与表达式的计算,如parr++
和parr=arr
是有效的,而arr=parr
和arr++
是无效的
4.数组的各元素在内存中是连续的,可以通过索引下标的方式arr[i]
获取任意一个元素,而arr[i+1]
一定代表下一个元素(除非数组索引越界),arr[i-1]
一定代表前一个元素(除非没有前一个元素)
5.因为数组名也是指针,所以也可以将获取元素的方式写成*(arr)
,它等价于arr[0]
,即代表第一个元素的值。同理,*(arr+1)
等价于arr[1]
即表示第二个元素,*(arr+i)
等价于arr[i]
即表示第i+1个元素
6.也就是说,arr
代表第0个元素的地址,arr+1
代表第2个元素的地址,arr+i
代表第i+1个元素的地址
7.也可以直接通过指针的加减法运算取得对应位置的元素地址。parr
代表的是第一个元素(index=0)的地址,parr+1
代表第二个元素(index=1)的地址,parr+i
代表第i+1个元素(index=i)的地址
8.所以,*(parr)
代表的是数组第一个元素的值,*(parr+1)
代表数组第二个元素的值,*(parr+i)
代表数组第i+1个元素的值
9.实际上,数组索引下标运算就是先转换成对应的指针,再通过指针去取得对应元素的。所以,使用指针的效率比使用索引下标取数组值的效率要高,它少了一个转换过程。或者说,指针和数组的索引是一一对应的关系。
10.由于数组名指向的是数组的第一个元素,如果某个指针指向这个数组中的某个元素,那么可以说这个指针指向的就是一个子数组。例如arr是原始数组,那么parr+3
是一个子数组,arr+4
也是一个子数组。这使得我们可能访问到数组第一个元素之前的元素(即父数组中子数组之前的元素),比如-1、-2在操作上都是允许的,除非这样的访问超越了父数组的边界。
2.指针和数组之间的几个等价概念
等价的方式 | 意义
--------------------------------|---------------------
&arr[i] arr+i parr+i | 都表示index=i元素的地址
--------------------------------|---------------------
arr[i] *(arr+i) *(parr+i) | 都表示index=i元素的值
特别的,当i=0时:
&arr[0] arr parr 都表示数组第一个元素的地址
arr[0] *(arr) *(parr) 都表示数组第一个元素的值
3.指针运算
指针是变量,可以直接参与表达式的运算,指针是地址,可以进行地址运算。
有效的指针运算包括:
- 相同类型指针之间的相互赋值运算
- 指针与整数之间的加、减法运算。这种运算可以让指针前移或后移N个数组的元素
- 指向相同数组中元素的两个指针之间的减法或比较运算(指针与指针之间只能进行减法和比较),减法运算得到的结果是指针之间的元素个数(例如
(arr+3) - arr + 1
表示第1个元素到第4个元素之间的4个元素) - 0赋值给指针的运算、0转换成指针类型的空、指针和0之间的比较
- 其它的运算方式都是非法的
对于指针和整数之间的加减法或指针的自增、自减运算,需要注意的是这些运算符之间的优先级以及从右向左计算的方式。
parr += 1
表示将指针向后移动一位,等价于++parr
。
*++parr
表示取下一个数组元素,因为一元运算符*
和++
的优先级相同,它们从右向左运算。
*parr++
表示取得parr当前指向的元素,但是parr已经指向下一个元素了。
指针之间可以比较大小,当然,只有指向同一数组的多个指针之间的比较才有意义。p和q两个指针,如果p指向的元素在q指向的元素之前,那么p < q
。通过比较指针,也可以很容易判断数组的访问是否越界。例如,判断指针指向的元素是否在第99个元素之后,对于只有100个元素的数组来说,这就是在判断越界。
parr > &arr[99]
parr > arr + 99 // 与上等价
同理,指向同一数组的多个指针之间可以进行减法运算(只能进行减法),指针之间的减法运算返回的是这两个指针之间的元素个数。
4.指针、数组和函数
C语言是按值拷贝的。
但因为数组名本身就是指向第一个元素的指针,所以按值拷贝也只是拷贝这个指针,拷贝得到的指针副本仍然指向数组的第一个元素,并且通过这个指针能够遍历到后面的元素。
因为拷贝后得到的副本指针指向的仍然是函数外面的数组结构,所以在函数内部可以直接通过这个指针修改外部数组。
下面两种想要以数组作为参数的函数在行为上是等价的:
void func1(int arr[]){}
void func1(int *parr){}
调用该函数时,都可以传递数组名或指针给它们:
int arr[];
int *parr;
parr = arr;
func1(arr);
func1(parr);
C指针和数组的关系详解的更多相关文章
- C++ 值传递、指针传递、引用传递详解
C++ 值传递.指针传递.引用传递详解 最近写了几篇深层次讨论数组和指针的文章,其中提到了“C语言中,所有非数组的形式参数传递均以值传递形式” 数组和指针背后——内存角度 语义"陷阱&quo ...
- slf4j log4j logback关系详解和相关用法
slf4j log4j logback关系详解和相关用法 写java也有一段时间了,一直都有用slf4j log4j输出日志的习惯.但是始终都是抱着"拿来主义"的态度,复制粘贴下配 ...
- 【转】UML类图与类的关系详解
UML类图与类的关系详解 2011-04-21 来源:网络 在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(D ...
- 005-Scala数组操作实战详解
005-Scala数组操作实战详解 Worksheet的使用 交互式命令执行平台 记得每次要保存才会出相应的结果 数组的基本操作 数组的下标是从0开始和Tuple不同 缓冲数组ArrayBuffer( ...
- Linux Shell数组常用操作详解
Linux Shell数组常用操作详解 1数组定义: declare -a 数组名 数组名=(元素1 元素2 元素3 ) declare -a array array=( ) 数组用小括号括起,数组元 ...
- UML类图与类的关系详解
摘自:http://www.uml.org.cn/oobject/201104212.asp UML类图与类的关系详解 2011-04-21 来源:网络 在画类图的时候,理清类和类之间的关系是重点.类 ...
- Hibernate中的多对多关系详解(3)
前面两节我们讲到了一对一的关系,一对多,多对一的关系,相对来说,是比较简单的,但有时,我们也会遇到多对多的关系,比如说:角色与权限的关系,就是典型的多对多的关系,因此,我有必要对这种关系详解,以便大家 ...
- slf4j log4j logback log4j2关系详解和相关用法
来源:slf4j log4j logback关系详解和相关用法https://www.cnblogs.com/Sinte-Beuve/p/5758971.html The Simple Logging ...
- main.js index.html与app.vue三者关系详解
main.js index.html与app.vue三者关系详解 2019年01月23日 11:12:15 Pecodo 阅读数 186 main.js与index.html是nodejs的项目启 ...
随机推荐
- Makefile = ?= := 区别 $@,$^,$<
= 是最基本的赋值:= 是覆盖之前的值?= 是如果没有被赋值过就赋予等号后面的值+= 是添加等号后面的值 1.“=” make会将整个makefile展开后,再决定变量的值.也就是说,变量的值将会是整 ...
- JS获取键盘事件
<script type="text/javascript" language=JavaScript charset="UTF-8"> docume ...
- Ubuntu上安装使用WeChat、TIM
WeChat可以直接到软件商店安装,不过是网页版...(其实个人感觉还行,就是什么都不能设置就挺蛋疼的,字体大小.背景什么的) 以下是网上找到的教程,在此总结一下: 下载地址:https://gith ...
- ssm知识点整理
第1章 resultType和resultMap的区别是什么? MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType ...
- cadence布线约束规则设置
DRC检查规则在布线过程中是必不可少的,包括时序规则,走线规则,间距规则,信号完整性规则和物理规则等,在绘制电路板时,设计相关规则满足设计需求,是非常关键的! https://wenku.baidu. ...
- jieba库的使用与词频统计
1.词频统计 (1)词频分析是对文章中重要词汇出现的次数进行统计与分析,是文本 挖掘的重要手段.它是文献计量学中传统的和具有代表性的一种内容分析方法,基本原理是通过词出现频次多少的变化,来确定热点及其 ...
- Flutter
2015年, Google 内部开始测试另一种高性能的编程方式,那就 Google 的 Sky 项目.Sky 项目使用网页开发语言Dart开发原生Android 应用,强调应用的运行速度和与 Web ...
- SSIS - 8.FTP 任务
FTP全称为 File Transfer Protocol(文件传输协议),是通过TCP网络将文件从一个服务器传输到另一个服务器.在SSIS包中,FTP任务是用来实现FTP功能的. 一.创建FTP连接 ...
- iOS URL Schemes与漏洞的碰撞组合
iOS URL Schemes与漏洞的碰撞组合 前言 iOS URL Schemes,这个单词对于大多数人来说可能有些陌生,但是类似下面这张图的提示大部分人应该都经常看见: 今天要探究的就是:了解iO ...
- [Swift]LeetCode70. 爬楼梯 | Climbing Stairs
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...