【C语言】12-指向一维数组元素的指针

C语言指针重点难点整理(详解)(包括一维数组,二维数组的元素指针,二维数组的行指针做函数参数,指针数组,行指针数组) C语言指针重点难点整理(详解)(包括一维数组,二维数组的元素指针,二维数组的行指针做函数参数,指针数组,行指针数组) 笔者学指针之前: 呵呵,听闻指针是C语言的难点,我倒要见识一下,到底有多难 笔者学完指针之后: 我还是收拾行囊,离开吧! 但是,在我的内心经过反复的挣扎,终于我决定,我要战胜它,现在,笔者已经大概弄清楚了指针的知识点,今天周末,刚好整理一下指针的一些难以理解的地方,和一些重点... 阅读详情

说明:这个C语言专题,是学习iOS开发的前奏。也为了让有面向对象语言开发经验的程序员,能够快速上手C语言。如果你还没有编程经验,或者对C语言、iOS开发不感兴趣,请忽略

前面我们已经学习了指针,如果指针存储了某个变量的地址,我们就可以说指针指向这个变量。数组及其数组元素都占有存储空间,都有自己的地址,因此指针变量可以指向整个数组,也可以指向数组元素。

一、用指针指向一维数组的元素

复制代码
 1 // 定义一个int类型的数组
 2 int a[2];
 3 
 4 // 定义一个int类型的指针
 5 int *p;
 6 
 7 // 让指针指向数组的第0个元素
 8 p = &a[0];
 9 
10 // 修改所指向元素的值
11 *p = 10;
12 
13 // 打印第一个元素的值
14 printf("a[0] = %d", a[0]);
复制代码

输出结果:,说明已经通过指针间接修改了数组元素的值,跟指向一个普通int类型变量是一样的。

由于数组名代表着数组的首地址,即a == &a[0],因此第8行代码等价于:

// 让指针指向数组的第0个元素
p = a;

内存分析图如下,一个指针变量占用2个字节,一个int类型的数组元素占用2个字节

 

二、用指针遍历数组元素

1.最普通的遍历方式是用数组下标来遍历元素

复制代码
1 // 定义一个int类型的数组
2 int a[4] = {1, 2, 3, 4};
3 
4 int i;
5 for (i = 0; i < 4; i++) {
6     printf("a[%d] = %d \n", i, a[i]);
7 }
复制代码

输出结果:

 

2.接下来我们用指针来遍历数组元素

先定义一个指针,指向数组的第一个元素

// 定义一个int类型的数组
int a[4] = {1, 2, 3, 4};

// 定义一个int类型的指针,并指向数组的第0个元素
int *p = a;

p的值是a[0]的地址,因此,现在我们利用指针p只能访问数组的第0个元素a[0],用*p就可取出a[0]的值1。要想访问其他元素,就必须拿到元素的地址,可以发现每个元素的地址差值为2,因为在16位编译器环境下,一个int类型的变量占用2个字节。现在只是知道a[0]的地址值为p,怎么根据a[0]的地址获取其他元素的地址呢?其实非常简单,p+1就是a[1]的地址。注意了,这里的p+1代表着p的值加2,并不是p的值加1,比如p的值为ffc3,p+1则为ffc5,而非ffc4。依次类推,p+2就是a[2]的地址ffc7,p+3就是a[3]的地址ffc9。

我先解释一下,为什么p+1代表p的值加2,而不是加1呢?

其实,p+1不一定代表p的值加2,也可能是加1、加4或者加8。究竟加多少,这跟指针的类型有关。下图是在16位编译器环境下的情况。

聪明的你可能已经找到规律了,因为char类型的变量要占用1字节,所以p+1代表p的值加1;float类型的变量占用4字节,所以p+1代表p的值加4。从这一点,也可以很好地说明为什么指针一定要分类型,不同类型的指针,p+1的含义是不一样的。

上述代码中的p指向了int类型的数组元素a[0],所以p+1代表p的值加2。知道怎么获取其他元素的地址了,那么就可以利用指针p遍历数组元素了。

复制代码
 1 // 定义一个int类型的数组
 2 int a[4] = {1, 2, 3, 4};
 3 
 4 // 定义一个int类型的指针,并指向数组的第0个元素
 5 int *p = a;
 6 
 7 int i;
 8 for (i = 0; i < 4; i++) {
 9     // 利用指针运算符*取出数组元素的值
10     int value = *(p+i);
11     
12     printf("a[%d] = %d \n", i, value);
13 }
复制代码

注意第10行的代码,*(p+i)代表根据p+i的值(其实就是第i个数组元素的地址)访问对应的存储空间,并取出存储的内容(也就是取出第i个数组元素的值),赋值给左边的value。

最后的输出效果是一样的:。注意的是:遍历完毕后,指针变量p还是指向a[0],因为p值一直没有变过,一直都是a[0]的地址ffc3

补充一下,其实第10行改成下面的代码也是可以的:

int value = *(a+i);

大家都知道,a值代表数组的首地址,也就是a[0]的地址ffc3。a+1则代表a的值加2,即a[1]的地址ffc5,也就是说,a+i代表着元素a[i]的地址。相信大家也能猜出来了,a+1不一定代表着a值加2,究竟加多少,取决于数组的类型a+i的计算方法与p+i相同

 

利用上面的方法遍历完数组元素后,p一直指向元素a[0]。其实我们也可以直接修改p的值来访问数组元素,只需要改一下第10行的代码即可

// 利用指针运算符*取出数组元素的值
int value = *(p++);

p++其实就是相当于p = p + 1,直接修改了p值,而且每次是加2。因此,每执行一次p++,指针p就会指向下一个数组元素。

输出结果肯定是一样的:。但是,遍历完毕后,指针变量p没有指向任何数组元素,因为一共执行了4次p++,最后p值为ffcb。当然,可以重新让p指向a[0]:p = &a[0];或者p = a;

注意,这里的写法是错误

int value = *(a++);

a++相当于a=a+1,数组名a是个常量!不能进行赋值运算!

 

三、指针与数组的总结

p是指针,a是一个数组

1> 如果p指向了一个数组元素,则p+1表示指向数组该元素的下一个元素。比如,假设p = &a[0],则p+1表示a[1]的地址

2> 对于不同类型的数组元素,p值的改变是不同的。如果数组元素为int类型,p+1代表着p的值加上2(16位编译器环境下)

3> 如果p的初值是&a[0],那么

  • p+i和a+i都可以表示元素a[i]的地址,它们都指向数组的第i个元素。a代表数组首地址,a+i也是地址,它的计算方法与p+i相同
  • *(p+i)和*(a+i)都表示数组元素a[i]
  • 虽然p+i和a+i都指向数组的第i个元素,但二者使用时还是有区别的。因为作为指针变量的p可以改变自身值,如p++,使p的值自增。而数组名a是一个代表数组首地址的常量,它的值是不能改变的,即a++是不合法的

4> 引用一个数组元素可以有两种方法:

  • 下标法: 如a[i]
  • 指针法: 如*(p+i) 或 *(a+i)

 

四、数组、指针与函数参数

1.用数组名作为函数实参时,是把实参数组的首地址传递给形参数组,两个数组共同占用同一段内存空间,这样形参数组中的元素值发生变化就会使实参数组的元素值也同时变化

复制代码
 1 void change(int b[]) {
 2     b[0] = 10;
 3 }
 4 
 5 int main()
 6 {
 7     // 定义一个int类型的数组
 8     int a[4] = {1, 2, 3, 4};
 9 
10     // 将数组名a传入change函数中
11     change(a);
12     
13     // 查看a[0]
14     printf("a[0]=%d", a[0]);
15     
16     return 0;
17 }
复制代码

change函数的形参是数组类型的,在第11行调用change函数时,将数组名a,也就是数组的地址传给了数组b。因此数组a和b占用着同一块内存空间。

输出结果:

 

2.这种地址的传递也可以用指针来实现。函数的实参和形参都可以分别使用数组或指针。这样就有4种情况:

也就是说,如果一个函数的形参类型是一个数组,调用函数时,你可以传入数组名或者指针变量;

复制代码
 1 void change(int b[]) {
 2     b[0] = 10;
 3 }
 4 
 5 int main()
 6 {
 7     // 定义一个int类型的数组
 8     int a[4] = {1, 2, 3, 4};
 9     
10     int *p = a;
11 
12     // 将数组名a传入change函数中
13     change(p);
14     
15     // 查看a[0]
16     printf("a[0]=%d", a[0]);
17     
18     return 0;
19 }
复制代码

注意第1行的形参类型是个数组int b[],第10行定义了指针变量p,第13行将p当做实参传入函数

 

如果一个函数的形参类型是一个指针变量,调用函数时,你可以传入数组名或者指针变量。

复制代码
 1 void change(int *b) {
 2     b[0] = 10;
 3     // 或者*b = 10;
 4 }
 5 
 6 int main()
 7 {
 8     // 定义一个int类型的数组
 9     int a[4] = {1, 2, 3, 4};
10 
11     // 将数组名a传入change函数中
12     change(a);
13     
14     // 查看a[0]
15     printf("a[0]=%d", a[0]);
16     
17     return 0;
18 }
复制代码

注意第1行的形参类型是个指针变量int *b,第12行将数组名a当做实参传入函数。

由第2行可以看出,在很多情况下,指针和数组是可以相互切换使用的。但是,并不能说指针就等于数组。

MTK眼中6G物理层与无线协议的进化之路 提议统一波束和小区级的测量、报告和切换框架/流程,进一步减少移动性切换过程中的中断,采用可扩展框架/流程,允许在不同移动性场景中进行部分用户设备配置更新以实现快速切换,支持用户设备发起的移动性(同步/切换)以降低延迟和因信令交换导致的失败,设计移动性RS以实现空闲状态下的节能和连接状态下的无缝用户体验,实现5G/6G间的无缝互操作移动性,为固定无线接入(FWA)提供潜在增强,构建统一的跨层移动性框架以降低复杂度、减少中断和失败。为适应多样化的流量类型,需要灵活的帧结构和高层时间对齐。 阅读详情

相关推荐

基于迁移学习的花卉识别系统

本研究采用了预训练的经典深度学习模型,包括ResNet、AlexNet和VGG,通过微调的方式在Oxford-102数据集和一个自制花卉数据集上进行训练,并对图像进行了多种数据增强操作,以提高模型的泛化能力,致力于实现花卉的高效分类。

m0_71146337的博客 2339

C语言 12-指向一维数组元素指针

本文目录 一、用指针指向一维数组元素 二、用指针遍历数组元素 三、指针与数组的总结 四、数组、指针与函数参数   说明:这个C语言专题,是学习iOS开发的前奏。也为了让有面向对象语言开发经验的程序员,能够快速上手C语言。如果你还没有编程经验,或者对C语言、iOS开发不感兴趣,请忽略。   前面我们已经学习了指针,如果指针存储了某个变量的...

weixin_30274627的博客 755

BOM Management Software:在一个集中式数据库中管理Excel物料清单(BOM)-开源

物料清单管理系统(BMMS)是一个实时协作软件应用程序,专门用于组织和管理电子零件和物料清单数据。 它使多个用户可以并行工作,并支持包括版本控制在内的高级功能。 它与Ciiva电子组件搜索API完全集成,可将组件库和物料清单与所有其他相关信息源无缝集成到一个集中式数据库中。

C语言基础:指针

指针】 一、指针变量与定义 C语言有两种变量:其中变量(普通变量)存储内容值;地址变量(指针变量)存储地址值。 1、定义格式 类型名 *指针变量名;*指针变量的标志,不包含在变量名里 注: (1)定义变量(普通变量、指针变量)都必须在前面有类型名。前类型后分号为定义语句。除此之外,其它语句都是执行语句。 (2)在定义指针变量时,指针变量名前的 * 表示现定义的是一个...

chxchxkkk的博客 889

5.30C++:指向一维数组指针、左值与右值,返回封装数组元素的引用

指向数组的指针 参考此篇文章: C语言指向一维数组指针 int array[5] = {1, 2, 3, 4, 5}; // 定义数组 int (*ptr)[5] = &array; // 定义指向数组的指针 指针都是指向一种类型。所谓类型, 不过是对内存中数据的解释的约定。 对于int a[5] ,可以将 具有5个int元素的数组认为是一种类型,这种类型在内存上的特点是连续存储5个整形数据。 例如 int (*ptr)[5] ,ptr这个指针就是指向这种类型的指针,ptr是一个指向数组的指针

weixin_44478659的博客 748

C语言指向一维数组指针

int array[5] = {1, 2, 3, 4, 5}; // 定义数组 int *intptr = array; // 定义指向数组元素指针 int (*arrayptr)[5] = &amp;array; // 定义指向数组的指针 上述三条语句分别定义了数组, 指向数组元素指针指向数组的指针. 内存情况如图示: 对于指向数组元素指针很好理解, 但是怎样理解 指向数组的指针...

Roger's Blogs 5万+

C语言二维数组指针指向二维数组的指针)详解

声明!本文转载仅为方便学习使用! 如有需要,请访问C语言二维数组指针指向二维数组的指针)详解 二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; 从概念上理解,a 的分布像一个矩阵: 0 1 2 3 4 5 6 7 8 9 10 11 但在内存中,a 的分布是一维线性的,整

weixin_43323830的博客 2万+

C语言指向数组的指针指向数组首元素指针

本文探讨了C语言指向数组的指针指向数组首元素指针的区别。虽然它们在数值上可能相同,但类型不同导致指针运算时的行为差异:指向元素指针加减以元素大小为步长,而指向数组的指针则以整个数组大小为步长。文章通过具体示例展示了三种指针定义方式(int*int(*)[n]、int[])的地址运算差异,并说明指向数组的指针访问元素时需要先解引用。特别强调在多维数组场景下,正确理解这些指针类型差异对编程至关重要,错误使用会导致地址计算错误。

博客是兴趣使然,大家互相学习 3037

C语言 指针数组和指向指针指针

针对自己在学习指针知识的时候比较难理解,特意整理出来,防止后面忘了,也拿出来供大家理解 指针数组的概念: 一个数组的元素值为指针则是指针数组。 指针数组是一组有序的指针的集合。 指针数 组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。 指针数组说明的一般形式为:类型说明符 *数组名[数组长度] 其中类型说明符为指针值所指向的变量的类型 指针数组类型表示的是多个指针(一组有...

tingguan的博客 9901
上一篇: 【C语言】11-指针
下一篇: 【C语言】13-指针和字符串
SpeedyCoder
博客等级 码龄14年 415粉丝 7原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值