c语言的指针详解ppt,最全的C语言指针详解.ppt

253b171540df25e1b84436cbe50dfc72.gif最全的C语言指针详解.ppt

第6章 指针,6.1 指针定义与使用 6.2 指针与函数 6.3 指针与数组 6.4 指针与字符串 6.5 指针数组与多级指针 6.6 指针与动态内存分配 6.7 指针的深层应用,6.1 指针的引出,一. 地址与指针 1. 地址与取地址运算 C程序中的变量在内存中占有一个可标识的存储区, 每一个存储区是由若干个字节组成, 每一个字节都有 自己的地址, 而一个存储区的 地址是指该存储区中 第一个字节的地址,C语言允许在程序中使用变量的地址 通过地址运算符 数组变量 a 的地址 数组名 a,2. 指针与指针变量 1 变量的访问方式 直接访问 通过变量名或地址访问变量的存储区 例 scanf “d” , , 间接访问 将一个变量的地址存放在另一个变量中. 如将变量 x 的地址存放在 变量p 中, 访问x 时先找到p, 再由p 中存放的地址找到 x2012,1010,1010,2 指针 一个变量的指针就是该变量的地址指针就是地址 3 指针变量 存放变量地址的变量, 它用来指向另一个变量,二、 指针变量的定义 1. 格式 数据类型 * 指针变量名 ; 例 int *p1 ; char *p2 ;,2. 说明 1 在变量定义时, * 号表示该变量是指针变量 注意 指针变量是p1 , p2 , 不是*p1 , *p2 2 定义指针变量后, 系统为其分配存储空间, 用以存放 其他变量的地址, 但在对指针变量赋值前, 它并没有 确定的值, 也不指向一个确定的变量,例 int x , *p ; x 5 ;,2012,1010,5,1234,注 指针变量p的值是随机值, 此时p 和 x 并无关联,3 使指针变量指向一个确定的变量必须进行赋值,int x , *p ; x 5 ; p ,2012,1010,5,1010三、 指针变量的引用 1. 指针运算符 * 1 p与*p不同, p是指针变量, p的值是p所指向的变量的地址 *p 是p 所指向的变量 , *p的值是p所指向的变量的值,*p 的值为 5*p 表示 x , 而p 的值为 1010,2 引用指针变量时的 * 与 定义指针变量时的 * 不同 定义变量时的 * 只是表示其后的变量是指针变量,int a , *p ; p ,2012,1010,5,101012,让p指向a,对a 重新赋值 等价于 a12,即,p 的值为a 的地址, *p 的值为2 p 的值不变 , *p 的值为 3,2 c *p ;,c *p ; c *p ; p ; 执行后 c 的值为 3 , *p 的值为 5,3 d *p ;,d *p ; p ; d *p ; 执行后 d 的值为 3 , *p 的值为 3,2012,1010,10101 p , 等价于 a ; 1012,3,31014,3,例6. 2 include void main int *p1 , *p2 , *p , a , b ; scanf“dd”, , temp x ; x y; y temp; void main int a , b ; scanf“dd”, ,5,说明 该程序不能实现a 和b 的交换因为实参a , b 对形参 x , y 是“值传递”, x 和y 的变 化不影响a 和b 所以输出为 a5, b9,9,main,swap,5,5,9,9,56.2 指针与函数,例 6. 3 include void swap1int *p1 , int *p2 int temp; temp *p1 ; *p1 *p2; *p2 temp; void main int a , b , *pt1 , *pt2 ; scanf“dd”, , *temp *p1 ; *p1 *p2; *p2 *temp; ,说明 这种方法可能会破坏系统的正常 工作状态,因为temp是一个指针变量 但是在函数中并没有给temp一个确定 的地址,这样它所指向的内存单元是 不可预见的,而对*temp的赋值可能 带来危害,main, p p1 ; p1 p2; p2 p; , 例 int * fun int a , int b 函数体 ; 说明 定义一个返回指针值的函数与以前定义函数格式 基本类似, 只是在函数名前加 * , 它表明该函数返回一个 指针值 , 而这个指针值是指向一个 int 型数据,二、函数返回 指针,例 include include define SIZE 100 char bufSIZE ; char *pbuf ; char *alloc int n char *begin ; if pn bufSIZE beginp ; ppn; returnbegin; else returnNULL; ,void main char *p1,*p2 ; int i ; p1alloc10; strcpyp1,”123456789”; p2alloc5; strcpyp2,”abcd”; printf“bufpn”, buf; printf“p1pn”, p1; printf“p2pn”, p2; putsp1; putsp2; for i0 ; i15 ; i printf“c”, bufi; ,buf0 buf1 buf9 buf10 buf14 buf15 buf99,buf10buf,bufbuf101 2 9 0,a 0,10,buf15,buf10,5,函数的指针 函数的入口地址 在程序执行过程中调用函数时, 计算机会转去执行 函数体内的语句, 因此计算机必须知道函数在什么地方。 实际上函数在内存中也要占据一片存储单元, 这片存储 单元一个起始地址, 我们称其为函数的入口地址, 即函数的指针, 这个函数的入口地址是用函数名来表示。 因此我们可以定义一个指针变量, 让它的值等于 函数的入口地址, 然后可以通过这个指针变量来调用 函数, 该指针变量称为指向函数的指针变量,三、指向函数的 指针,指向函数的指针变量 1. 定义格式 数据类型 *指针变量名 形参表列 ; int *pt int arr , int n ; 说明 数据类型 指针变量所指向的函数的返回值类型 形参表列 即指针变量所指向的函数的形参表列 格式中的小括号不能省略,2. 应用 1 让指针变量指向函数 pt add ; 因为函数名为函数的入口地址, 所以直接将函数名 赋给指针变量即可 2 使用指针变量调用函数 格式 *指针变量名 实参表列,例 求一维数组中全部元素的和 include int add int b , int n; void main int a6 1, 3, 5, 7, 9, 11, total ; int *pt int b , int n ; pt add ; total *pt a , 6 ; printf “total d n” ,total ; int add int b , int n int i , sum 0 ; for i 0 ; in ; i sum sumbi; returnsum; ,定义指向函数 的指针变量,令指针变量pt 指向函数add,通过pt 调用 函数add,6.3 指针与数组,一. 一维数组与指针 1. 一维数组及元素的地址表示 int a5 1, 2, 3, 4, 5 ; 数组的地址 a,2. 用指针变量引用数组元素 1 定义指针变量 int *p , a5 1, 2, 3, 4, 5 ; p a ;,2 引用数组元素,注意 指针变量也可以加下标 pk 等价于 ak 分别用三种方法输出数组元素, 其效率不同, 下标法与地址法的效率相同, 指针法的效率较快 用指针变量访问数组元素时要注意下标是否越界,例 将数组a中全部元素加1, 再输出a include void main int a5 1, 3, 5 ,7 ,9 , *p , j ; for pa ; pa5 ; p printf“3d”, *p; printf“n” ; for j0 ; j5 ; j ajaj1 ; for j0 ; j5 ; j printf“3d”, *pj ; printf“n” ; ,pa ;a a1 a2 a3 a4,2,4,6,8,10,可以用p , 但不能用a 因为a 代表数组的起始地址 它是地址常量, 不能改变 而p 是一个指针变量,使用指针变量时要注意它的当前值3. 指向数组的指针变量作函数参数,例6. 7 实参和形参都用数组名 include void inv1 int x , int n int temp, i , j , mn-1/2; for i0 ; im ; i jn-1-i ; tempxi ; xixj ; xjtemp ; void main int i , a6 1, 3, 4, 6, 7, 9 ; inv1a , 6 ; for i0; i6; i printf“3d”, ai ; printf“n”; ,a0 a1 a2 a3 a4 a5,x0 x1 x2 x3 x4 x5,main,inv1,例6. 7 实参用数组名, 形参用指针变量 include void inv2int *x , int n int temp, mn-1/2; int *p , *i , *j ; ix ; jxn-1; pxm; for ; ip ; i, j temp*i ; *i*j ; *jtemp ; void main int i , a6 1, 3, 4, 6, 7, 9 ; inv2a , 6 ; for i0; i6; i printf“3d”, ai ; printf“n”; ,a0 a1 a2 a3 a4 a5,inv2,9,1,7,3,6,4,1,a1,a4,a2,a3,3,4,i和j的指向会变化, p的指向保持不变,例6.7 实参和形参都用指针变量 include void inv3int *x , int n; void main int *p , a61, 3, 4, 6, 7, 9; p a ; inv3 p , 6 ; for pa ; pa6 ; p printf“3d”, *p ; printf“n”; void inv3int *x , int n int temp, mn-1/2; int *p , *i , *j ; ix ; jxn-1; pxm; for ; ip ; i, j temp*i ; *i*j ; *jtemp ; ,例6.7 实参用指针变量, 形参用数组名 include void inv4int x , int n; void main int *p, a61, 3, 4, 6, 7, 9; p a ; inv4 p , 6 ; for pa ; pa6 ; p printf“3d”, *p ; printf“n”; void inv4int x , int n int temp, i , j , mn-1/2; for i0 ; im ; i jn-1-i ; tempxi ; xixj ; xjtemp; 例6.8 求数组中最大和最小元素 include int max , min ; void m1int arr , int n int *p , *end ; endarrn ; maxmin*arr ; forparr1 ; pmax max*p ; else if *pmin min*p ; void main int i , a6; fori0 ; i6 ; i scanf“d”, ,a0 a1 a2 a3 a4 a5,4 7 1 9 0 54,4,7,9,1,0二、二维数组与指针,二维数组的定义,对于二维数组a,首先可以把它先理解为一个一维数组, 它有3个元素 a0, a1, a2,而每一个元素又是一个一维数组, 包含4个元素 如a0是一维数组, 它有4个元素 a00, a01, a02, a03,a34,a0, a1, a2只是一种地址表示方法, 并不真的二维数组元素,可以看作是第二重一维数组的名字。,二维数组的初始化,1 可以分行给二维数组赋初值,int a341,2,3,4,5,6,7,8,9,10,11,12;,1 2 3 4,5 6 7 8,9 10 11 12,2 可以将所有数据写在一个花括号中,按顺序对各元素赋初值,int a341,2,3,4,5,6,7,8,9,10,11,12;,二维数组的初始化,3 可以对部分元素赋初值,其余元素补0,int a341,5,9;,int a341,0,6,0,0,11;,4 如果对全部数据都赋初值,则定义时第一维的长度可以不指定,但第二维的长度不能省,int a 41,2,3,4,5,6,7,8,9,10,11,12;,二维数组的初始化,如果只对部分数据赋初值,第一维的长度也可以不指定,但元素必须分行赋初值,int a 40,0,30,10;,二维数组的地址,二维数组名a表示二维数组的首地址, 也是第0个元素a0的地址,a1代表第1个元素a1的地址 a1 p,include void main int a341,2,3,4,5,6,7,8,9,10,11,12; int *p; for pa0; pa012; p printf“d ”, *p; printf“n ”;,指向二维数组元素的指针,int a34; int p; pa; 合法吗,int x36, *q,p; q,2010,2026,p是二级指针, 它指向一个整型指针变量q, 而q指向一个整型变量a是一种地址表示方法, a实际指向了第一重一维数组元素a0,而 a0是第二重一维数组,非法,指向二维数组元素的指针,定义格式类型名 (*指针变量名)数组长度;,int a34; int *p4; pa;,p指向一个包含有4个整型数据的一维数组,合法,虽然在定义p的时候只用了一个*,但p实际上是一个二级指针变量,指向二维数组元素的指针,例2输出二维数组中的元素,include void main int a341,2,3,4,5,6,7,8,9,10,11,12; int *p4, i, j; pa; for i0; i3; i for j0; j4; j printf“6d”, **pij ; printf“n”; ,指向二维数组元素的指针,二维数组用得较多的是“字符串数组”,配合字符串的操作,使字符串处理更加方便、灵活。,char a4256“Pascal“,“VC“,“Basic“,“Java“;,P a s c a l,V c,B a s i c,J a v a,include include define MAXLEN 256 define N 4 void main int i, j; char tempMAXLEN; char nameNMAXLEN“Pascal“,“VC“,“Basic“,“Java“; fori0; iN; i putsnamei; ,书的数量,fori0; i0 strcpytemp, namei; strcpynamei, namej; strcpynamej, temp; ,选择法排序,书名的最大长度1,指向二维数组元素的指针,比较两个字符串大小,复制字符串,Quiz 选择法排序,Assignment,1、将数组a23中的每个元素向右移一列, 最后一列换到最左一列(如右图所示) 要求必须用指针实现,2、将数组aMN中的每个元素向右移一列, 最后一列换到最左一列 要求必须用指针实现,Experiment,实验题目指向二维数组的指针编程 实验目的深入理解如何用指针变量表示二维数组的 元素和元素的地址,学会用指向二维数组 的指针变量作函数参数 实验内容编程找出二维数组中的鞍点,二维数组的 鞍点是指在该位置上的元素在该行上最大, 在该列上最小,也可能没有鞍点。要求必 须用指针实现。 编写一个找鞍点的函数,用指向二维数组 的指针变量作函数参数,6.4 指针与字符串,一、字符指针 1. 定义指向字符串的指针变量 char *p “China”; 说明 这里没有定义字符数组, 但字符串在内存中还是以数组 形式存放的. 字符串在内存中 占有一片连续的存储单元, 以0结束,注意 赋值只是把字符串的首地址赋给p , 而不是把字符串赋给 p, p 是一个指针变量, 它不能存放一个字符串, 只能存放一个地址,2460 2461 2462 2463 2464 2465将字符串的 首地址赋给p,2. 输出字符串 printf“sn” , p ; 输出字符串时, 先输出p 指向的 第一个字符, 然后系统自动执行p, 使p 指向下一个字符, 再输出该字符, 直到遇到0 为止 也可以用循环逐个输出字符串中的字符 for ; *p0; p printf“c”, *p ;,2460 2461 2462 2463 2464 2465,2461,2462,2463,2464,2465,二、 字符数组与字符指针变量的区别 char s “C Language” ; char *p “C Language” ;,1. 存储方式不同 s 存放的是字符串中的字符和0 p 存放的是字符串的首地址,2. 虽然s 和p 都能代表字符串的首地址, 但s是数组名, 是一个常量, 而p是一个指针变量, 因此 s 的 写法是错的, 而p 的写法是对的,char *p1, *p2 “abcd”; p1 “China” ;,char s12 , str “good” ; s12 “China” ; s “China” ;,4. 定义数组s 时, 系统会给s 分配一片连续的存储单元 定义指针变量p 时, 只给p 分配一个存储单元,三、字符串指针作函数参数,例6. 20 实现字符串复制 void copystrchar from , char to int i 0 ; while fromi0 toi fromi ; i; toi 0 ; void mani char a “cat” , b “tiger”; putsa; putsb; copystra , b; putsa; putsb; ,a,b,c,a,t,0,相当于biai,例 6. 20 void copystrchar *from , char *to for ; *from0 ; from , to *to *from ; *to 0 ; void main char *a “cat” , *b “tiger”; putsa; putsb; copystra , b; putsa; putsb; ,a,b,c,a,t,0,a1,b1,a2,b2,a3,b3,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值