手把手教你学单片机的C语言程序设计(十四).pdf_第1页
手把手教你学单片机的C语言程序设计(十四).pdf_第2页
手把手教你学单片机的C语言程序设计(十四).pdf_第3页
手把手教你学单片机的C语言程序设计(十四).pdf_第4页
全文预览已结束

手把手教你学单片机的C语言程序设计(十四).pdf.pdf 免费下载

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

篁 ,厂 一 _ 葺 l 匿 豳 指针是 C语言 中的一个重 要概 念,指针类型数据在 C语言程序中的 使用十分普遍。 C语言区别于其它程序 设计语言的主要特点就是处理指针时 所表现出的能力和灵活性。 正确地使用指针类型数据。 可以有 效地表示复杂的数据结构 。 直接处理内 存地址。 而且可以更为有效合理地使用 数组。 计算机程序的指令、 常量和变量等 都要存放在以字节为单位的内存单元 中, 内存的每个字节都具有一个唯一的 编号。 这个编号就是存储单元的地址。 各个存储单元中所存放的数据。 称 为该单元的内容。 计算机在执行任何一 个程序时都要涉及到许多的单元访问。 就是按照内存单元的地址来访问该单 元中的内容, 即按地址来读或写该单元 中的数据。 由于通过地址可以找到所需 要的单元, 因此这种访问是“ 直接访问” 方式。 另外一种访问是“ 间接访问” , 它首 先将欲访问单元的地址存放在另一个 单元中。 访问时, 先找到存放地址 的单 元。 从中取出地址。 然后才能找到需访 问的单元。 再读或写该单元的数据。在 这种访问方式中使用了指针。 C语言中引入了指针类型的数据 。 指针类型数据是专门用来确定其他类 型数据地址的。 因此一个变量的地址就 称为该变量的指针。例如 。 有一个整型 变量 i 存放在内存单元 6 0 H中。 则该内 存单元地址 6 0 H就是变量 i 的指针。 如果有一个变量专门用来存放另 一 个变量的地址 。 则该变量称之为指向 变量的指针变量 ( 简称指针变量) 。例 如,如果用另一个变量 p i 存放整型变 量 i 的地址 6 0 H,则 p i 即为一个指针 变量。 指针变量与其它变量一样。 必须先 定义。 后使用。 指针变量定义的一般形式: 数据类型 i 暑 导 类型】 指针变量名; 其中。 “ 指针变量名” 是我们定义的 指针变量名字。 “ 数据类型” 说明了该指 针变量所指向的变量的类型。“ 存储器 类型 是可选项 。 它是 C 5 1 编译器的一 种扩展 。 如果带有此选项 , 指针被定义 为基于存储器的指针。无此选项时, 被 定义为一般指针。 这两种指针的区别在 于它们的存储字节不同。 一般指针在内 存中占用 3 个字节 。 而基于存储器的指 针。 则指针的长度可为 1 个字节( 存储 器类型选项为 i d a t a 、 d a t a 、 p d a t a) 或 2 个字节 ( 存储器 类型选项 为 c o d e 、 x d a t a ) 。 例如: i n t p t : 定义一个指向对象类型为 i n t 的一 般指针 , 指针自身在默认的存储区( 由 编译模式决定 ) , 指针长度为 3个字节。 c h a r x da t a p a; 在 x a t a 存储器中定义一个指向的 对象类型为 c h a r 的基于存储器的指 针。指针自身在默认的存储器区域( 由 编译器决定 ) 。 长度为 2字节。 f lo a t x da t a d a t a p b; 在 x a t a 存储器中定义一个指向的 对象类型为f l o a t 的基于存储器的指针。 指针自身在 d a t a区。 长度为2 字节。 特别要注意。 变量的指针和指针变 量是两个不同的概念。 变量的指针就是 该变量的地址 。 而一个指针变量里面存 放 的内容是另一个 变量在内存中的地 址 。 拥有这个地址的变量则称为该指针 变量所指向的变量。 每一个变量都有它 自己的指针( 1 P 地址) , 而每一个指针变 量都是指向另一个变量的。 为了表示指 针变量和它所指向的变量之间的关系。 C语言 中用符号“” 来表示“ 指向 。例 如 。 整型变量 i 的地址 6 0 H存放在指针 变量 p i 中。 则可用 p i 来表示指针变量 p i 所指向的变量, 即 p i 也表示变量 j 。 指针变量是含有一个数据对象地 址 的特殊变量, 指针变量中只能存放地 址。在实际的编程和运算过程中, 变量 的地址和指针变量的地址是不可见的。 因此, C语言提供了一个取地址运算符 。 使用取 地址运算符“ 和赋值运算 符“ = ” 就可以使一个指针变量指向一 个变量。 例t 1 :1 : i n t t : i n t p t : D t =t : 通过取地址运算和赋值运算后。 指 针变量 p t 就指向了变量 t 。 当完成了变量、 指针变量的定义以 及指针变量的引用后。 我们就可以对内 存单元进行间接访问了。此时。 我们需 用到指针运算符( 又称间接运算符) “ 。 例如。 我们需将变量 t 的值赋给变量 X 。 1 n t x : i n t t : 直接访问方式为: x = t : 间接访问方式为: i n t x : i n t t : f n t p t : p t =l : x = p t ; 有关的运算符有两个 , 它们是。 维普资讯 和“ ” 0在不同的场合所代表的含义是 不同的, 我们一定要搞清楚。 例如: i n t p t ; 进行指针变量的定 义 , 此时 p l 的 为指针变量说明符。 p l = l : 此时 l 的 为取 t 的地址 并赋给 p l ( 取地址 ) 。 = p t ; 此时 p l 的 为指针运算 符 ,即将指针变量 p l 所指向的变量值 赋给 x ( 取内容 ) 。 任何变量都占有存储单元, 都有地 址。数组及其元素同样占 有存储单元, 都有相应的地址。因此, 指针既然可以 指向变量, 当然也可以指向数组。 其中, 指向数组的指针是数组的首地址, 指向 数组元素的指针则是数组元素的地址。 例如: 我们定义一个数组 【 10 】 和一个指 向数组的指针变量 p x ; i n t x 【 l O 】 : i n t p x ; 当我们未对指针变量 p 进行引 用时, p 与x I O 毫不相干, 即此时指针 变量 p 并未 指向数组 a 1 0 。 当我们将数组的第一个元素的地 址 x 【 0 赋予 p x时, P x = x 【 0 I 旨 针变 量 p x即指向数组 【 。这时, 可以通过 指针变量 p 来操作数组 X了,即 p 代 表 X 【 0 】 , ( p x + 1 ) 代表 X 【 1 】 , ( p x + i ) 代表 【 1 。i =1 、 2 、 。 C语言规定, 数组名代表数组的首 地址,也是第一个数组元素的地址 , 因 此上面的语句也可改写为: i n t 【 10 】 : i n t p x ; p x = x ; 形式上更简单一些。 若先使指针 变量 p 指向数组 【 】 ( 即 p x = x ; ) , 则: 1 p + + ( 或 p + = f ) : 将使指针变量 p 指向下一个数组元素, 即 1 。 2 p x + + : 因为 + +与 运算符优先 级相同, 而结合方向为自右向左, 因此, p + +等价于 ( p + + ) 。 3 + + p :先使 p 自加 1 ,再取 p 值。 若 P的初值为乙扎 0 】 , 则 执行 X二 , P干十时, X值为 a O】 的值 , 而执行 x二。十十 P后, 则 x 值 等于 a 【 1 的值。 4 ( p ) + + : 表示 p 所指向的元素 值加 I 。要注意的是元素值加 1而不是 指针变量值加 I 。 要特别注意对 p x + i 的 含义的理解。C语言规定: p x + l 指向数 组首地址的下一个元素, 而不是将指针 变量 p 的值简单地加 1 , 例如: 若数组 的类型是整型( i n 1 ) , 每个数组元素 占2 个字节 ,则对于整型指针变量 p 来 说, p x + l 意味着使 p 的原值 ( 地址) 加 2个字节, 使它指向下一个元素。 指针除了可以指向一维数组外, 也 可以指向多维数组。 下面以二维数组为 例进行说明。 假定我们 已定义了一个三行四列 的二维数组: i n t x 【 3 【 4 = 1 , 3 , 5 ,7 1 , 9 , 1 1 , 1 3 , 1 5 , ”7 , 1 9 , 2 1 , 2 3 对这个数组 的理解为 : X是数组 名,数组包含 3个元素: X【 0 、 x 1 】 、 X 【 2 。 每个元素又是一个一维数组, 包含 4个元素。如 x 【 0 代表的一维数组包含 【 0 】 【 O 】 = 1 , 【 0 】 【 1 】 = 3 ) , 【 0 】 【 2 】 = 5 , X 【 0 】 【 3 】 = 7 。 从二维数组的地址角度看, X代表 整个数组的首地址 , 也就是第 0行的首 地址。x + l代表第 1 行的首地址 , 即数 组名为 【 1 】 的一维数组首地址。 根据 C语言的规定,由于 x O 】 、 X 【 1 、 【 2 】 都是一维数组, 因此它们分别 代表了各个数组的首地址。即 【 0 = 【 0 】 【 0 】 , x 1 】 = x 【 1 【 0 】 , 【 2 】 = 【 2 】 【 0 】 。 我们 同时定义一个指针变量 I n l ( p ) 【 4 】 : 其含义是 P指向一个包含 4个 元素的一维数组。 当p = x时, 指 向数组 【 3 】 【 4 】 的第 0行首址。 P +I 和 +1 等价,指向数组 x 3 】 【 4 的第 1行首址。 P + 2和 x + 2等价 ,指向数组 x 3 【 4 】 的第 2行首址。 ( P +1 ) + 3和 【 1 【 3 】 等价, 指向数 组 x 1 【 3 】 的地址。 ( ( P + 1 ) + 3 ) 和 【 1 【 3 】 等价 , 表示 X 【 1 【 3 的值。 一 般地, 对于数组元素 j 】 来讲: ( p + i ) + j 就相当于 【 i 【 j 】 , 表示数 组第 i 行第 i 列的元素的地址。 ( ( p + i ) + j ) 就相当于 【 i】 【 j 】 , 表示数 组第 i 行第 i 列的元素的值。 下面我们做 实验 ,感性认识 一 下指针。 - 。 在 L E D 1 6 2字符液晶试验板上 做实验, 分别采用直接引用变量和间接 引用变量的方法。 将变量值显示在数码 管上。 在我的文档 中建立一个文件 目录 ( c s 3 6) , 然后建立 c s 3 6 u v 2的工程项 目。 最后建立源程序文件( c s 3 6 C o 输入下面的程序 : # in c l u d e I I 序号( 以下同) : 1 2 v o id ma i n ( v o i d ) 1 1 3 f 4 c h a r a l b : 1 1 5 c h a r p : 6 p = b : 1 1 7 a = 0 x 8 0 ; 1 1 8 p = 0 x 8 0 ; 1 1 9 P O = b ; I I 1 0 P 3 = a ; I I 1 1 w h i l e ( 1 ) : 1 1 2 I 1 1 3 编译通过后 ,将生成的 c s 3 6 h e x 文件烧录到 8 9 S 5 1芯片中。将芯片插 入到 L E D 1 6 2字符液晶试验板上, 试 维普资讯 望 ,厂 _ - 置 l 国 譬 曩 圃 验板上接通 9 V电源 , 可以看到 , 个位 数码管和千位数码管均显示“ 8 ” 。 我们对程序进行分析解释。 序号 1 ( 程序解释 , 以下同 ) : 包含 头文件 R E G5 1 H。 序号 2 : 程序分隔。 序号 3 :定义函数名为ma i n的主 函数。 序号 4 : ma i n主函数开始。 序号 5 : 定义字符型局部变量。 序号 6 : 定义指向字符型数据类型 的指针变量 P 。 序号 7 : 将变量 b的地址赋给指针 变量 P。 即指针指向变量 b 。 序号 8: 采用直接引用变量的方法 赋值 0 x 8 0给变量 a 。 序号 9 : 采用间接引用变量的方法 赋值 0 x 8 0给指针变量 P指向的变量 ( 即变量 b o 序号 1 0 : P 0口显示变量 b 。 序号 1 1 : P 3口显示变量 a 。 序号 1 2 : 动态停机。 序号 1 3 : ma in主函数结束。 蠢 鏊 。 在 L E D 1 6 2字符液晶试验板上 。 分别用下标法和指针法引用数组元素 并在数码管上显示。 在我的文档中建立一个文件 目录 ( c s 3 7) 。 然后建立 c s 3 7 u v 2的工程项 目, 最后建立源程序文件( c s 3 7 c o 输入下面的程序: # in c lu d e 序号( 以下同) : 1 # d in e u c h a r u n s ig n e d c h a r f1 2 # d e f i n e u i n t u n s i g n e d in t 3 , “ 4 , v o id d e la y ( u i n t k ) 5 6 u in t i ,j = 7 f o r ( i = O : i fl序号( 以下同) : 1 # d e f i n e u c h a r u n s i g n e d c h a r 2 u c h a r c o d e S E G 7 1 0 = 0 x c 0 , 0 x f 9 ,0 x a 4 , 0 x b 0 , 0 x 9 9 ,0 x 9 2 , 0 x 8 2 , 0 x f 8 , 0 x 8 0 , O x g O ; 3 s b it P 3 _ 0 = P 3 O : 4 , = = 一一一= 一= = = 一5 v o id s w a p ( u c h a r x , u c h a r y ) : 6 , = 一一= 一=一= 一一7 v o id ma i n ( v o id ) 8 9 u c h a r a = 3 , b = 8 : 1 0 u c h a r p t l , p t 2 ; 1 1 p t l = a : 1 2 p t 2 = & b ; 1 3 P 1 = S E G7 a ; 1 4 P 0 = S E G7 b ; 1 5 w h il e ( 1 ) 1 6 f 、 , , 1 7 P 3 = 0 x ; 1 8 if ( ! P 3 _ O ) 1 9 s w a p ( p t l , p t 2 ) ; 2 0 P 1 = S E G 7 a ; 2 1 P 0 = S E G 7 b ; 2 2 w h i le ( 1 ) : 2 3 、| | 2 4 l 2 5 一一一一= 一=一= 2 6 v o id s wa p ( u c h a r x , u c h a r Y ) 2 7 2 8 u c h a r t : 2 9 t = x : 3 0 蓥 维普资讯 x = y : 3 1 y = t : 3 2 l 3 3 编译通过后,将生成的 C S 3 8 h e x 文件烧录到 8 9 S 5 1芯片中,将芯片插 入到 L E D 1 6 * 2字符液晶试验板上, 试 验板上接通 9 V电源 ,右边 2个 L E D 数码管显示 “ 3 8 ” 。按下 3号键右边 2 个 L E D数码管显示“ 8 3 ” 。 显然, 结果完 全相 同。 我们分析程序。 序号 1( 程序解释,以下同 ) :包含头文件 RE G51 H。 序号 2 : 数据类型的宏定义。 序号 3 : 数码管 0 9的字形码。 序号 4 : 定义 P 3 0 。 序号 5 : 程序分隔。 序号 6 : 子函数s w a p声明。 序号 7 : 程序分隔。 序号 8: 定 义函数名 为 ma i n的主函数。 序号 9 : m a in主函数开始。 序号 1 O :定义无符号字符型局部变量 a 、 b 并赋初值。 序号 1 1 :定义指向字符型数据类型的指针 变量 p t l及 p t 2 。 序号 1 2 : p t l 指向变量 a 。 序号 1 3 : p t 2 指向变量 b 。 序号 1 4 : 变量 a 的值送 P 1 13 显示。 序号 1 5 : 变量 b的值送 P O 13 显示。 序号 1 6 : 无限循环。 序号 1 7 : 无限循环语句开始。 序号 1 8 : P 3口置 O x O f , 以便读取 P 3 0的输 入状态。 序号 1 9: 如果 P 3 0为低电平。 序号 2 O : 调用 s w a p子函数 , 传递的是变量 a 、 b的地址。 序号 2 1 : 此时变量 a的值送 P 1 13 显示。 序号 2 2 : 此时变量 b的值送 P 0 13显示。 序号 2 3 : 动态停机。 序号 2 4 : 无限循环语句结束。 序号 2 5 : m a i n 主函数结束。 序号 2 6 : 程序分隔。 序号 2 7 : 定义函数名为s w a p的子函数。 序号 2 8 : s w a p子函数开始。 序号 2 9 : 定义无符号字符型局部变量t 。 序号3 0 : X 指向的指针变量( 即变量a ) 1 直 送 t 。 序号 3 1 : y 指向的指针变量( 即变量 b ) 值送 X指 向的指针变量( 即变量 a o 序号 3 2 : 再将变量 t 赋给 Y 指向的指针变量 ( 即变量 b o这样实现了变量 a 、 b的交换。 序号3 3 : s w a p子函数结束。 鞠 _ 在 手把手教你学单片机的 C语 言程序设计( 十三 ) 中, 我们曾经介绍 过。 除了可以用变量作为函数的参数之 外。还可以用数组名作为函数的参数。 这里我们做一个有关的实验, 求出一个 一 维数组 a 1 1 中的前 1 0个数之和, 将其存放在 a 1 0 中, 并在 L E D 1 6 2 字符液晶试验板的数码管上显示出来。 在 我 的 文档 中建 立一 个 文 件 目录 ( c s 3 9) 。 然后建立 c s 3 9 u v 2的工程项 目。 最后建立源程序文件( c s 3 9 C o 输入下面的程序 : # i n c lu d e 序号( 以下同) : 1 # d e f in e u c h a r u n s i g n e d c h a r 2 #de f ine uin t u ns ign ed i n t 3 u c h a r c o d e S E G 7 1 O = O x c O ,0 x f 9 ,0 x a 4 , 0 x b 0 , 0 x 9 9 , 0 x 9 2 , 0 x 8 2 ,0 x f 8 ,0 x 8 0 , 0 x 9 0 ; 4 , 5 v o i d s u m( u in t q u in t n ) 6 f 7 u i n t i , s : 8 u i n t t : 9 t = q : 1 0 f o r ( i = O : i n : i+ + ) s = s + ( t + i ) : 1 1 t = q +l O : 1 2 t = s : 1 3 l 1 4 1 5 v o id ma i n ( v o id ) 1 6 f 1 7 u i n t a 1 1 】 = O , 1 , 2 , 3 ,4 , 5 ,6 , 7 , 8 , 9 , O l : 1 8 u i n t p t ,l e n = l O : 1 9 p t = a ; 2 0 s u m( a , le n ) ; 2 1 P 3 = S E G7 a 1 0 1 o o o ; 2 2 P 2 = S E G7 ( a 1 0 1 O O ) 1 O : 2 3 P 1 = S E G7 ( a 1 o 1 O ) 1 O 】 : 2 4 P 0 = S E G7 a 1 0 1 1 O : 2 5 wh i le ( 1 ) : 2 6 l 2 7 编译通过后 。将生成的 c s 3 9 h e x 文件烧录到 8 9 S 5 1 芯片中,将芯片插 入到 L E D 1 6 2字符液晶试验板上 。 试 验板上接通 9 V电源 , 4个 L E D数码管 显示 “ 0 0 4 5 ” 。 对程序进行分析。 序号 1( 程序解释,以下同 ) :包含头文件 RE G51 H 序号 2 、 3 : 数据类型的宏定义。 序号 4 : 数码管 0 9的字形码。 序号 5 : 程序分隔。 序号 6 : 定义函数名为s u m的子函数。 序号 7 : s u m子函数开始。 序号 8 : 定义无符号整型局部变量 i 、 S 。 序号 9 : 定义指向无符号整型数据类型的指 针变量 t 。 序号 1 0 : q传递的数组首地址赋予 t ,指针 变量 t 指向数组的首单元。 序号 1 1 : f 0 r 循环语句。 共循环 n 次, 将数组 a的前 n 个元素累加后存入s 。 序号 1 2 : 指针变量 t 指向数组 a 的最后一个 单元 a 1 O 1 。 序号 1 3 : 将 S 存入 a 1 0 。 序号 1 4 : s u m子函数结束。 序号 1 5 : 程序分隔。 序号 1 6 : 定义函数名为 m a i n 的主函数。 序号 1 7 : m a i n 主函数开始。 序号 1 8 : 定义无符号整型数组 a 并赋初值。 序号 1 9 : 定义指向无符号整

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论