本节书摘来自异步社区《指针的编程艺术(第二版)》一书中的第3章,第3.1节,作者 蔡明志,更多章节内容可以访问云栖社区“异步社区”公众号查看

第三章 指针与数组

指针的编程艺术(第二版)
3-1 指针与一维数组

3-2 指针与二维数组

3-3 数组指针

3-4 为什么parr等同于 *parr?

3-5 指向数组的指针

3-6 多重指针

3-7 命令行参数

3-8 改错题

3-9 练习

3-10 程序实战

指针其实就是一个地址。数组的名称,表示这个数组的第1个元素的地址,所以它也是指针。由此可知,指针与数组的关系是很密切的。为了与指针变量(pointer variable){XE "指標變數(pointer variable)"}有所区别,我们称数组名就是指针常量(pointer constant){XE "指標常數(pointer constant)"}。指针变量与指针常量的不同之处在于,前者可以使用递增运算符(++)或递减运算符(--)来递增和递减指针;但后者不行。因此,如果在程序中使用arr++或arr--,就会出现错误的信息。

3.1 指针与一维数组

指针的编程艺术(第二版)
我们先来看一下指针与一维数组(one dimension array)的关系。请参阅范例pointerArr1-5。

范例pointerArr1-5

/* pointerArr1-5.c */
#include <stdio.h>
#include <conio.h>int main()
{int arr[]= {100, 101, 102};int *ptr = arr;int i, size = 0;size = (sizeof arr/ sizeof (arr[0]) );/* ------------Using arr--------------*/  printf("使用 arr 指针常量来表示:\n");for(i = 0; i < size; i++)printf("&arr[%d] = %x\n", i, &arr[i]); printf("\n");   for(i = 0; i < size; i++)printf("arr+%d = %x\n", i, arr+i);printf("\n");for(i = 0; i < size; i++)printf("arr[%d] = %d\n", i, arr[i]); printf("\n");for(i = 0; i < size; i++)printf("*(arr+%d) = %d\n", i, *(arr+i)); /*--------------Using ptr-------------*/printf("\n使用ptr 指针变量来表示:\n");for(i = 0; i < size; i++)printf("ptr+%d = %x\n", i, ptr+i);printf("\n");for(i = 0; i < size; i++)printf("ptr[%d] = %d\n", i, ptr[i]); printf("\n");for(i = 0; i < size; i++)printf("*(ptr+%d) = %d\n", i, *(ptr+i)); getch();return 0;
}

输出结果


从输出结果可以知道,arr是数组名,它是指针常量,而ptr是指针变量。arr表示这个数组第1个元素的地址,也就是arr等同于&arr[0]。

arr可以使用指针变量的符号,如arr等同于arr[0],(arr+1) 等同于arr[1],依此类推。同理,ptr也可以使用指针常量的[]符号,例如,当前ptr所指向变量地址的值为ptr[0],它等同于ptr,而ptr[1]等同于*(ptr+1),依此类推。

再来看范例pionterArr1-10。

范例pointerArr1-10

/* pointerArr1-10.c */
#include <stdio.h>
#include <conio.h>
int main()
{int i[] = {100, 200, 300, 400, 500};int *ptr = i+2;int k;printf("ptr[-2]=%d\n", ptr[-2]);printf("ptr[-1]=%d\n", ptr[-1]);printf("ptr[0]=%d\n", ptr[0]);printf("ptr[1]=%d\n", ptr[1]);printf("ptr[2]=%d\n\n", ptr[2]);ptr++;printf("After executing ptr++....\n");printf("ptr[0]=%d\n", ptr[0]);printf("*(ptr+0)=%d\n", *(ptr+0));printf("ptr[1]=%d\n", ptr[1]);printf("*(ptr+1)=%d\n", *(ptr+1));getch();return 0;
}

输出结果


ptr与i数组的关系图如下所示。


程序一开始将ptr指向i+2(它是i[2] 的地址),所以ptr[0] 等于i[2],因为ptr[0]表示当前ptr所指向变量地址的值。同时也知道ptr[-1] 是i[1]、ptr[-2] 是i[0]、ptr[1]是i[3]、ptr[2] 是i[4]。我们从这个范例得到以下的公式

ptr[i] == *(ptr+i)

大部分的用户都是用*(ptr+i)间接访问数组中索引为i的元素值。

当指针与++递增运算符一起运算时,必须注意++的作用对象在哪里,是对地址加1,还是将变量值加1。如果是对地址加1,则将指针移到下一元素的地址。请参阅范例pointerAnd++。

范例pointerAnd++

/* pointerAnd++.c */
#include <stdio.h>
#include <conio.h>int main()
{int i[] = {100, 200, 300, 400, 500};int *pi = i;printf("i=%p, pi=%p\n", i, pi);printf("i[0]=%d\n", i[0]);printf("*pi=%d\n\n", *pi);pi+1;printf("After pi+1, pi=%p\n", pi);;printf("*pi=%d\n\n", *pi);pi++;printf("After pi++, pi=%p\n", pi);printf("*pi =%d\n", *pi);getch();return 0;
}

输出结果


从输出结果可知,pi+1只是将当前的pi向下移到下一个元素的地址,它并没有覆盖pi。而pi++不仅将当前的pi移到下一个元素的地址,而且还将它的新值还覆盖了pi。我们可以对指针变量pi做++的动作,但不可以对数组名i做++的动作。

当指针、递增运算符(++){XE "遞增(++)運算子" y "ㄉㄧˋㄗㄥㄩㄣˋㄙㄨㄢˋㄗˇ"}或递减运算符(--){XE "遞減(--)運算子" y "ㄉㄧˋㄐㄧㄢˇㄩㄣˋㄙㄨㄢˋㄗˇ"},及 * 这3个运算符同时出现时,要注意++的作用点在哪里。请参阅范例pointerAnd++2。

范例pointerAnd++2

/* pointerAnd++2.c */
#include <stdio.h>
#include <conio.h>int main()
{int i[] = {100, 200, 300, 400, 500};int *pi = i;printf("...%d\n", *pi++);printf("*pi = %d\n", *pi);printf("...%d\n", *++pi);printf("*pi = %d\n", *pi);printf("...%d\n", ++*pi);printf("*pi = %d\n", *pi);getch();return 0;
}

输出结果


从程序定义中

int i[ ] = {100, 200, 300, 400, 500};
  int *pi = i;

得知,其示意图如下。


下一条语句

*pi++;

和++在同一个语句中时,要注意++的作用对象,是对地址加1还是对值加1。如果对地址加1,表示将pi指针移到下一地址。由于和++的运算优先级相同,且其结合性是由右至左,因此pi++其实就是(pi++),但这里的++为后置加,所以先得到*pi为100之后,才会处理++的动作。因此语句先输出100,再将pi指向下一个地址。如下图所示。


接下来的

*++pi;

由于这条语句相当于(++pi),这里的 ++ 是前置加,所以pi指针先移到了下一个地址,再输出pi的值(300),如下图所示。


最后

++*pi;

这条语句相当于++(pi),由此可知,++是针对pi的值加1,这条语句等同于

*pi = *pi + 1;

pi(= 300)加1,再放入pi中,如下图所示。


最后,*pi的运算结果为301

《指针的编程艺术(第二版)》一第三章 指针与数组3.1 指针与一维数组相关推荐

  1. (矩阵分析基础(第二版)第三章 矩阵的分解 3.3埃尔米特(hermite)矩阵及其分解)

    (矩阵分析基础(第二版)第三章 矩阵的分解 3.3埃尔米特(hermite)矩阵及其分解) 文章目录 (矩阵分析基础(第二版)第三章 矩阵的分解 3.3埃尔米特(hermite)矩阵及其分解) 1.埃 ...

  2. JavaScript DOM编程艺术第二版学习(1/4)

    接下来项目需要网页相关知识,故在大牛的指引下前来阅读本书. 记录方式:本书分四部分阅读,完成阅读之后会多写一篇包括思维导图的算是阅读指南的东西,浏览的童鞋看着指南可以跳过一些不必要的坑~ 当前水平:H ...

  3. 算法竞赛入门经典(第二版)第三章习题

    声明:作者水平有限,只是会基础C语言的小菜,C++还未入门.作者仅根据算法竞赛入门经典(第二版)书上第三章习题所述题意而编写,并未严格按照原题的输入输出编写,代码仅经过个人测试(OJ网站太慢了).代码 ...

  4. 【我的JS第三本】JavaScript_DOM编程艺术第二版读书笔记

    经过前一段时间HTML&CSS的学习,感觉视频加读书是一个比较不错的学习方法,两者相辅相成,互相补充,所以也准备看看关于JavaScript的书. 2015年12月14日,之前使用韩顺平老师的 ...

  5. Python核心编程(第二版)第六章部分习题代码

    6-2字符串标识符.修改例 6-1 的 idcheck.py 脚本,使之可以检测长度为一的标识符,并且可以识别 Python 关键字,对后一个要求,你可以使用 keyword 模块(特别是 keywo ...

  6. RFID第二版答案-第三章

    3.1 波特率和比特率有什么不同? 比特率:表示的是每秒钟传输的二进制的位数,单位为bit/s 波特率:表示的是每秒钟传输的码元数. 3.2 信道宽度为3kHz,波特率可以达到8kbaud码?若能请给 ...

  7. 数据管理知识体系指南(第二版)-第三章——数据治理-学习笔记

    目录 3.1引言 3.1.1业务驱动因素 3.1.2目标和原则 3.1.3基本概念 3.2活动 3.2.1规划组织的数据治理 3.2.2制定数据治理战略 3.2.3实施数据治理 3.2.4嵌入数据治理 ...

  8. 《指针的编程艺术(第二版)》一3.8 改错题

    本节书摘来自异步社区<指针的编程艺术(第二版)>一书中的第3章,第3.8节,作者 蔡明志,更多章节内容可以访问云栖社区"异步社区"公众号查看 3.8 改错题 指针的编程 ...

  9. 《指针的编程艺术(第二版)》一3.10 程序实战

    本节书摘来自异步社区<指针的编程艺术(第二版)>一书中的第3章,第3.10节,作者 蔡明志,更多章节内容可以访问云栖社区"异步社区"公众号查看 3.10 程序实战 指针 ...

  10. 《Python核心编程》第二版第36页第二章练习 -Python核心编程答案-自己做的-

    <Python核心编程>第二版第36页第二章练习 这里列出的答案不是来自官方资源,是我自己做的练习,可能有误. 2.21 练习 2-1. 变量,print和字符串格式化操作符.启动交互式解 ...

最新文章

  1. 计算机二级第十七套真题,2012年计算机二级VB第十七套上机试题及解析.doc
  2. 【必读】2019年深度学习自然语言处理最新十大发展趋势, 附报告下载
  3. 【资源总结】“十大深度学习方向” 专栏
  4. 深度学习入门之感知器(原理+代码)
  5. jenkins ssh发布配置
  6. PE格式详细讲解11 - 系统篇11|解密系列
  7. C++string容器-字符串比较
  8. 想学C语言?这些你一定要知道
  9. elasticsearch java_java Elasticsearch详细介绍及使用实例分析
  10. ArcGIS案例学习笔记-手动编辑擦除挖空挖除相减
  11. 配置管理——配置项标识
  12. github1s 油猴插件
  13. Java自动生成5道100以内的加减法口算题
  14. 第十四周博客作业西北师范大学|李晓婷
  15. 运筹学-2-单纯形法的矩阵计算
  16. 超文本传输协议HTTP
  17. NNabla:索尼开源的一款神经网络框架
  18. Win10无法升级Win11体验版解决方法
  19. 删库不跑路-详解MySQL备份策略
  20. 计算机视觉之人脸识别(Yale数据集)--HOG和ResNet两种方法实现

热门文章

  1. 395.至少有K个重复字符的最长子串
  2. 用eclipse无法打开html里用绝对路径添加的图片但是在外面可以打开的解决方法
  3. 估计理论(1):最小方差无偏估计(第2章)
  4. 实例详解机器学习如何解决问题
  5. NLP系列(2)_用朴素贝叶斯进行文本分类(上)
  6. 语音识别基本原理介绍之gmm-hmm续
  7. 2018_09_25_参加医学人工智能大会的个人思考
  8. java基础学习(4)
  9. 长链剖分算法完整总结
  10. 边缘保留滤波matlab,【DIP】各种边缘保留滤波器一览