




已阅读5页,还剩123页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十章 指针 10 1地址和指针的概念10 2变量的指针和指向变量的指针变量10 3数组与指针10 4字符串与指针10 5指向函数的指针10 6返回指针值的函数10 7指针数组和指向指针的指针10 8有关指针的数据类型和指针运算的小结 10 1地址和指针的概念 为了说清楚什么是指针 必须弄清楚数据在内存中是如何存储的 又是如何读取的 内存区的每一个字节有一个编号 这就是 地址 如果在程序中定义了一个变量 系统就会给这个变量分配内存单元 按变量地址 即变量名 存取变量值的方式称为 直接访问 方式 2 另一种存取变量值的方式称为 间接访问 的方式 将变量的地址放在另一个内存单元中 先到另一个内存单元中取得变量的地址 再由变量的地址找到变量并进行数据存取 在 语言中 指针是一种特殊的变量 它是存放地址的 假设我们定义了一个指针变量i pointer用来存放整型变量的地址 它被分配地址为 3010 3011 的两个字节 可以通过语句 i pointer 将 的地址 2000 存放到i pointer中 这时 i pointer的值就是 2000 即变量 所占用单元的起始地址 要存取变量 的值 可以采用间接方式 先找到存放 的地址 的变量i pointer 从中取出 的地址 2000 然后到2000 2001字节取出 的值 一个变量的地址称为该变量的 指针 例如 地址2000是变量 的指针 如果有一个变量专门用来存放另一变量的地址 即指针 则它称为 指针变量 上述的i pointer就是一个指针变量 指针和指针变量的定义 指针变量的值 即指针变量中存放的值 是地址 即指针 请区分 指针 和 指针变量 这两个概念 10 2变量的指针和指向变量的指针变量 变量的指针 就是变量的地址 指针变量 存放变量地址的变量 用来指向另一个变量 为了表示指针变量和它所指向的变量之间的联系 在程序中用 符号表示 指向 例如 i pointer代表指针变量 i pointer是i pointer所指向的变量 见下图 可以看到 i pointer也代表一个变量 它和变量i是同一回事 下面两个语句作用相同 i 3 i pointer 3 例如 inti j int pointer 1 pointer 2 可以用赋值语句使一个指针变量得到另一个变量的地址 从而使它指向一个该变量 如 pointer pointer 10 1定义一个指针变量 定义指针变量的一般形式为 基类型 指针变量名 在定义指针变量时要注意两点 10 指针变量的引用 请牢记 指针变量中只能存放地址 指针 不要将一个整数 或任何其他非地址类型的数据 赋给一个指针变量 下面的赋值是非法的 pointer 1 100 pointer 1为指针变量 100为整数 两个相关的运算符 1 取地址运算符 2 指针运算符 例如 a为变量a的地址 p为指针变量p所指向的存储单元的内容 即p所指向的变量的值 例10 通过指针变量访问整型变量 includevoidmain int int pointer pointer pointer 1 a 把变量 的地址赋给pointer 1 pointer 2 b 把变量 的地址赋给pointer 2 printf printf pointer 1 pointer 2 对 和 运算符说明 如果已执行了语句pointer 1 pointer 的含义是什么 2 的含义是什么 3 pointer 相当于什么 相当于 a 即变量a的地址 相当于a 相当于 例10 2输入 和 两个整数 按先大后小的顺序输出 和 includevoidmain int 1 2 scanf 1 2 if printf printf max min 1 2 运行情况如下 交换前交换后 10 2 3指针变量作为函数参数 例10 3对输入的两个整数按大小顺序输出 includevoidmain voidswap int int int int pointer pointer scanf pointer pointer 2 if swap pointer pointer 2 printf voidswap int int inttemp temp 1 1 2 2 temp 运行情况如下 5 9 9 5 voidswap int int inttemp temp 1 1 2 2 temp int temp temp 1 1 2 2 temp voidswap int int inttemp temp 1 1 2 2 temp int p p p1 p1 p2 p2 p 调用函数不可能改变实参指针变量的值 但可以改变实参指针变量所指变量的值 例10 输入 3个整数 按大小顺序输出 includevoidmain voidexchange int 1 int 2 int 3 int scanf exchange printf voidexchange int int int voidswap int int if swap if swap if swap voidswap int pt1 int pt2 inttemp temp pt1 pt1 pt2 pt2 temp 10 3数组与指针 指针变量可以指向变量 当然也可以指向数组元素 把某一元素的地址放到一个指针变量中 所谓数组元素的指针就是数组元素的地址 定义一个指向数组元素的指针变量的方法 与以前介绍的指向变量的指针变量相同 例如 int 10 int 10 3 1指向数组元素的指针 对该指针变量赋值 把 元素的地址赋给指针变量 也就是使 指向 数组的第 号元素 如图 p 10 通过指针引用数组元素 C规定 如果指针变量p已指向数组中的一个元素 则p 1指向同一数组中的下一个元素 而不是将p值简单地加1 p 1所代表的地址实际上是p 1 d d是一个数组元素所占的字节数 对整型 d 2 对实型 d 4 对字符型 d 1 图10 13 如果p的初值为 a 0 则 1 p i和a i就是a i 的地址 指向a数组的第i个元素 见图10 13 a代表数组首地址 a i也是地址 它的计算方法同p i 即它的实际地址为a i d 例如 p 9和a 9的值是 a 9 指向a 9 2 p i 或 a i 是p i或a i所指向的数组元素 即a i 实际上 在编译时 对数组元素a i 就是处理成 a i 即按数组首地址加上相对位移量得到要找的元素的地址 然后找出该单元中的内容 3 指向数组的指针变量也可以带下标 如p i 与 p i 等价 引用一个数组元素 可以用 下标法 如 形式 指针法 如 或 其中 是数组名 是指向数组元素的指针变量 其初值 例10 5输出数组中的全部元素 假设有一个 数组 整型 有 个元素 要输出各元素的值有三种方法 1 下标法 includevoidmain int int for scanf printf for printf 2 通过数组名计算数组元素地址 找出元素的值 includevoidmain int int for scanf printf for printf 3 用指针变量指向数组元素 includevoidmain int int for scanf printf for printf 注意 1 可以改变指针变量的值 例如 上述第 3 种方法是用指针变量p来指向元素 用p 使p的值不断改变 这是合法的 如果不用p而使a变化 例如 用a for p a a p 10 a printf d a 是不行的 因为a是数组名 它是数组首地址 它的值在程序运行期间是固定不变的 是常量 a 是无法实现的 2 要注意指针变量的当前值 请看下面的程序 例10 通过指针变量输出 数组的 个元素 includevoidmain int for scanf printf for printf printf 我们先看一下运行情况 1234567890 22153234003003625202116318259823728483显然输出的数值并不是 数组中各元素的值 解决这个问题的办法 只要在第二个 循环之前加一个赋值语句 includevoidmain int for scanf printf p a for printf printf 3 指针变量的运算 先使p指向数组a 即p a 则 p 或p 1 使p指向下一元素a 1 p 等价于 p 先得到p指向的变量的值 即 p 即a 0 再使p 1 p p 先取 p 即a 0 再使p 1 p p 先使p 1 p 再取 p 即a 1 p 表示p所指向的元素值加1 即 a 0 10 3 3用数组名作函数参数 在第8章8 7节中介绍过可以用数组名作函数的参数如 voidmain voidf intarr intn intarray 10 f array 10 void intarr intn voidf intarr intn 在编译时是将arr按指针变量处理的 相当于将函数f的首部写成voidf int arr intn 因此 arr i 和 arr i 等价 实参数组名代表该数组首元素的地址 而形参是用来接收从实参传递过来的数组首元素地址的 因此 形参应该是一个指针变量 实际上 C编译都是将形参数组名作为指针变量来处理的 例10 将数组 中 个整数按相反顺序存放 includevoidmain voidinv int int int 10 printf Theoriginalarray for printf printf inv printf Thearrayhasbeeninverted for printf printf voidinv int int 形参x是数组名 inttemp for temp temp return 运行情况如下 Theoriginalarray Thearrayhasbeeninverted includevoidmain voidinv int int int printf Theoriginalarray for printf printf inv printf Thearrayhasbeeninverted for printf printf 对这个程序可以作一些改动 将函数inv中的形参 改成指针变量 voidinv int int 形参x为指针变量 int temp for temp temp return 归纳起来 如果有一个实参数组 想在函数中改变此数组中的元素的值 实参与形参的对应关系有以下 种情况 1 形参和实参都用数组名 如 voidmain void int int int 2 实参用数组名 形参用指针变量 如 void void int int int 3 实参形参都用指针变量 例如 voidmain void int int int p a p 4 实参为指针变量 形参为数组名 如 voidmain void intx int p a p includevoidmain voidinv int int int printf Theoriginalarray n for scanf printf inv 实参为指针变量 printf Thearrayhasbeeninverted for printf printf 例10 8用实参指针变量改写例10 7 voidinv int int int temp for temp temp return 例10 9用选择法对 个整数按由大到小顺序排序 includevoidmain voidsort int int int 10 for scanf sort for printf voidsort int int int for for 10 3 4多维数组与指针1 多维数组元素的地址设inta 3 4 1 3 5 7 9 11 13 5 17 19 21 23 可理解为a数组包含3个元素a 0 a 1 a 2 每一个元素又是一个包含4个元素的一维数组 如图所示 a 0 0 a 0 1 a 0 2 a 0 3 a 1 0 a 1 1 a 1 2 a 1 3 a 2 0 a 2 1 a 2 2 a 2 3 二维数组名a是代表a的首行 即第0行 的首地址 为2000故a 1 代表第1行首地址2008 2000 8a 2 代表第2行首地址2016 2008 8一维数组名a 0 表示a 0 的首元素 第0列 的地址 即 a 0 0 为2000一维数组名a 1 表示a 1 的首元素 第0列 的地址 即 a 1 0 为2008一维数组名a 2 表示a 2 的首元素 第0列 的地址 即 a 2 0 为2016故a 0 1 第0行第1列的地址 即 a 0 1 为2002a 1 1 第1行第1列的地址 即 a 1 1 为2010a 2 1 第2行第1列的地址 即 a 2 1 为2018如下图所示 所以 第i行第j列的元素的地址可表示为 a i j第i行第j列的元素可表示为 a i j a i a i a i j a i j a i j a i j a i j a i j a与a 0 的区别 a 二维数组名 指向行a 0 a 0 一维数组名 指向列元素a 0 0 故a 1 a 0 1在行指针前加一个 就转换为列指针 a 指向第0行0列的指针在列指针前面加 就成为行指针 a 0 指向第0行的指针 表示形式 含义 地址 二维数组名 第0行首地址2000 第0行0列元素a 0 0 的地址2000 第1行首地址2008 第1行0列元素a 1 0 的地址2008 第1行2列元素a 1 2 的地址2012 第1行2列元素a 1 2 的值值为13 a a 0 a 0 a a 1 a 1 a 1 a 1 a 1 2 a 1 2 a 1 2 a 1 2 a 1 2 a 1 2 inta 3 4 例10 0输出二维数组有关的值 include defineFROMAT voidmain int 3 4 1 3 5 7 9 printf printf 0 printf 0 0 0 printf 1 printf 1 0 printf printf printf 2 指向多维数组元素的指针变量 在了解上面的概念后 可以用指针变量指向多维数组的元素 1 指向数组元素的指针变量 例10 11用指针变量输出二维数组元素的值 includevoidmain inta 3 4 1 3 5 7 9 11 13 15 17 19 21 23 int p for p a 0 p a 0 12 p if p a 0 4 0 printf n printf 4d p printf n 运行结果如下 1357911131517192123 定位某个指定的数组元素 数组起始地址 相对位置 a i j 在数组a n m n行m列 中的相对位置的计算 i m j 之前有i行 每行有m个 之前还有j个 故a i j 的值可表示为 p i m j 开始时p a 0 0 例如 数组a 3 4 中的元素a 2 3 的值可表示为 p 2 4 3 即 p 11 如下图所示 2 指向由 个元素组成的一维数组的指针变量 例10 13输出二维数组任一行任一列元素的值 includevoidmain inta 3 4 1 3 5 7 9 11 13 15 17 19 21 23 int p 4 i j p a scanf printf 运行情况如下 本行为键盘输入 对int p 4 的理解 inta 4 a为数组名 有4个整型元素int p 4 p为数组名 有4个整型元素即 p是一个指向包含4个整型元素的一维数组的指针变量 故p是行指针 p i j是a数组第i行第j列元素的地址 即 p i j 是a i j 的值 3 用指向数组的指针作函数参数 例10 13有一个班 个学生 各学 门课 计算总平均分数以及第 个学生的成绩 用函数average求总平均成绩 用函数search找出并输出第 个学生的成绩 用指针变量作形参 两种方法 用指向变量的指针变量 用指向一维数组的指针变量 includevoidmain voidaverage float p intn voidsearch float p 4 intn floatscore 3 4 65 67 70 60 80 87 90 81 90 99 100 98 average score 12 求12个分数的平均分 search score 2 求序号为 的学生的成绩 voidaverage float int float p end floatsum 0 aver p end p n 1 for p p end p sum sum p aver sum n printf average 5 2f aver voidsearch float 4 int p是指向具有4个元素的一维数组的指针 int printf thescoreofNo are n n for printf 5 2 p n i 程序运行结果如下 average thescoreofNo 2are 例10 4在上题基础上 查找有一门以上课程不及格的学生 打印出他们的全部课程的成绩 includevoidmain voidsearch float p 4 intn 函数声明 floatscore 3 4 65 57 70 60 58 87 90 81 90 99 100 98 search score voidsearch float p 4 int int flag for flag for if p j i 60 flag 1 if flag 1 printf No dfails hisscoresare n j 1 for printf printf 程序运行结果如下 No 1fails hisscoresare 65 057 070 060 0No 2fails hisscoresare 58 087 090 081 0 10 字符串与指针 10 4 1字符串的表示形式 例10 5定义一个字符数组 对它初始化 然后输出该字符串 includevoidmain charstring printf string 1 用字符数组存放一个字符串 然后输出该字符串 2 用字符指针指向一个字符串 可以不定义字符数组 而定义一个字符指针 用字符指针指向字符串中的字符 例10 16定义字符指针 includevoidmain char string printf string char string string IloveChina 等价于 例10 17将字符串 复制为字符串 对字符串中字符的存取 可以用下标法 也可以用指针法 includevoidmain char amaboy 20 int for printf stringais printf stringbis for printf printf 也可以设指针变量 用它的值的改变来指向字符串中的不同的字符 例10 18用指针变量来处理例10 17问题 includevoidmain char Iamaboy 20 p1 p2 int p1 a p2 b for p1 p1 p2 p2 p1 p2 0 printf stringais printf stringbis for printf printf 程序必须保证使 和 同步移动 10 字符指针作函数参数 例10 19用函数调用实现字符串的复制 includevoidmain voidcopy string charfrom charto chara amateacher charb youareastudent printf stringa s nstringb s n a b printf copystringatostringb n copy string a b printf nstringa s nstringb s n a b 1 用字符数组作参数 voidcopy string charfrom charto int while from to from to 程序运行结果如下 copystringatostringb b 形参用字符指针变量 includevoidmain voidcopy string char from char to char Iamateacher char youareastudent printf stringa s nstringb s n a b printf copystringatostringb n copy string a b printf nstringa s nstringb s n a b voidcopy string char from char to for from 0 from to to from to 0 对copy string函数还可作简化 1 copy string函数的函数体还可写成 while from to from to 3 copy string函数的函数体还可改为 while to from 2 将copy string函数改写为 while to from 0 to from 将 from赋给 to 如果赋值后的 to值等于 则循环终止 已赋给 4 上面的while语句还可以进一步简化 while to from 它与下面语句等价 while to from 5 函数体中while语句也可以改用for语句 for to from 或for to from 10 对使用字符指针变量和字符数组的讨论 虽然用字符数组和字符指针变量都能实现字符串的存储和运算 但它们二者之间是有区别 主要有以下几点 1 字符数组由若干个元素组成 每个元素中放一个字符 而字符指针变量中存放的是地址 字符串第1个字符的地址 决不是将字符串放到字符指针变量中 2 赋值方式 对字符数组只能对各个元素赋值 不能用以下办法对字符数组赋值 charstr str 而对字符指针变量 可以采用下面方法赋值 char 但注意赋给 的不是字符 而是字符串第一个元素的地址 3 对字符指针变量赋初值 char loveChina 等价于char 而对数组的初始化 charstr loveChina 不能等价于charstr str 数组可以在定义时整体赋初值 但不能在赋值语句中整体赋值 4 如果定义了一个字符数组 在编译时为它分配内存单元 它有确定的地址 而定义一个字符指针变量时 给指针变量分配内存单元 在其中可以放一个字符变量的地址 也就是说 该指针变量可以指向一个字符型数据 但如果未对它赋予一个地址值 则它并未具体指向一个确定的字符数据 如 charstr scanf str 是可以的 而常有人用下面的方法 目的是想输入一个字符串 虽然一般也能运行 但这种方法是危险的 char scanf 应当这样 5 指针变量的值是可以改变的 如 例10 0改变指针变量的值 includevoidmain char IloveChina printf 运行结果 China 若定义了一个指针变量 并使它指向一个字符串 就可以用下标形式引用指针变量所指的字符串中的字符 例10 1 includevoidmain char loveChina int printf Thesixthcharacteris c n a 5 for printf 10 5指向函数的指针 10 5 1用函数指针变量调用函数 可以用指针变量指向整型变量 字符串 数组 也可以指向一个函数 一个函数在编译时被分配给一个入口地址 这个函数的入口地址就称为函数的指针 例10 22求 和 中的大者 先列出按一般方法的程序 includevoidmain intmax int int int scanf printf intmax int int int if else return 将main函数改写为 includevoidmain intmax int int int int int 定义p是指向函数的指针变量int max scanf d d a b 通过指针变量来调用函数printf a d b d max d a b c int p int int p是指针变量 指向函数 函数返回值为整型 int p int int p是函数 其返回值是指向整型变量的指针 函数名代表函数的入口地址 p max 使指针变量p指向函数max的入口地址见图10 35 注意 p是指向函数的指针变量 它只能指向函数的入口 不能指向函数中间的某一条指令 因此不能用 p 1 来表示函数的下一条指令 图10 35 关于用函数指针变量调用函数的说明 指向函数的指针变量的一般定义形式 数据类型 指针变量名 函数参数表列 函数的调用可以 通过函数名调用通过指向函数的指针调用 int p int int p是一个指向函数的指针变量 故将哪个函数的地址赋给它 它就指向哪一个函数 在给函数指针变量赋值时 只需给出函数名 如 p max 不能写成p max a b 用函数指针变量调用函数时 只需将 p 代替函数名 在 p 之后的括弧中根据需要写上实参 如 c p a b 对指向函数的指针变量 p n p p 等运算均无意义 10 返回指针值的函数 一个函数可以返回一个整型值 字符值 实型值等 也可以返回指针型的数据 即地址 其概念与以前类似 只是返回的值的类型是指针类型而已 这种返回指针值的函数 一般定义形式为类型名 函数名 参数表列 例如 int a int int 例10 4有若干个学生的成绩 每个学生有 门课程 要求在用户输入学生序号以后 能输出该学生的全部成绩 用指针函数来实现 includevoidmain floatscore 4 60 70 80 90 56 89 67 88 34 78 90 66 float search float pointer 4 intn float int printf enterthenumberofstudent scanf printf ThescoresofNo dare n m search score for printf 5 2f float search float pointer 4 int float pt pt pointer return pt 运行情况如下 enterthenumberofstudent ThescoresofNo are 56 0089 0067 0088 00 例10 5对上例中的学生 找出其中有不及格课程的学生及其学生号 includevoidmain floatscore 4 60 70 80 90 56 89 67 88 34 78 90 66 float search float pointer 4 float p int for search score if score printf scores for printf printf float search float pointer 4 inti float pt pt pointer 1 指向下一行首 即本行末尾for i 0 i 4 i if pointer i 60 pt pointer break 不及格则指向行首return pt 程序运行结果为No 1scores 50 0089 0067 0088 00No 2scores 34 0078 0090 0066 00 10 指针数组和指向指针的指针 10 指针数组的概念 一个数组 若其元素均为指针类型数据 称为指针数组 也就是说 指针数组中的每一个元素都相当于一个指针变量 一维指针数组的定义形式为类型名 数组名 数组长度 例如 为什么要用到指针数组呢 因为指针数组适合于用来指向若干字符串 使字符串处理更加方便灵活 例如 图书馆有若干本书 想把书名放在一个数组中 然后要对这些书目进行排序和查询 例10 6将若干字符串按字母顺序 由小到大 输出 include includevoidmain voidsort char name intn voidprint char name intn char name Followme BASIC GreatWall FORTRAN Computerdesign int sort nam
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 车辆采购招标方案(3篇)
- 废弃工业处置方案(3篇)
- 社区发展现状与未来趋势的综合分析
- 2025至2030全球及中国车辆路边援助行业产业运行态势及投资规划深度研究报告
- 幼儿园教师教学观察笔记
- 教育学原理真题
- 2025至2030全球及中国汽车轮轴行业发展趋势分析与未来投资战略咨询研究报告
- 2025-2030年农业批发产业市场发展分析及前景趋势与投资战略研究报告
- 2025-2030年中国锡中间体行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年中国街机游戏应用程序行业市场现状供需分析及投资评估规划分析研究报告
- 2025年高考数学全国一卷试题真题及答案详解(精校打印)
- 2022年广东省普通高等院校校招收中等职业学校毕业生统一考试英语试卷及答案
- 工会委员增补选举办法 工会委员选举办法
- 危险源辨识、风险评价清单(市政(管道)工程)
- DIN985 尼龙锁紧螺母
- 煤矸石综合利用复垦项目环评报告书
- 我的家乡福州PPT课件
- C5116A立式车床的PLC控制
- 曲线正矢、付矢、超高、加宽(中分法)计算表
- 北师大版初中数学定理、公式汇编(共20页)
- 迎风飘扬的旗歌谱二声部
评论
0/150
提交评论