C语言程序设计指针

上传人:s9****2 文档编号:570498989 上传时间:2024-08-04 格式:PPT 页数:46 大小:303.51KB
返回 下载 相关 举报
C语言程序设计指针_第1页
第1页 / 共46页
C语言程序设计指针_第2页
第2页 / 共46页
C语言程序设计指针_第3页
第3页 / 共46页
C语言程序设计指针_第4页
第4页 / 共46页
C语言程序设计指针_第5页
第5页 / 共46页
点击查看更多>>
资源描述

《C语言程序设计指针》由会员分享,可在线阅读,更多相关《C语言程序设计指针(46页珍藏版)》请在金锄头文库上搜索。

1、C 语言程序设计语言程序设计指针指针周闻钧朱宏明本讲内容本讲内容n地址与指针的概念n变量、数组、字符串、函数指针及其指针变量n指针数组及二级指针不掌握指针就没掌握不掌握指针就没掌握C的精华的精华n n指针是指针是C C语言中的一个重要的概念,也是语言中的一个重要的概念,也是C C语言的语言的一个重要特色一个重要特色n n正确而灵活地运用指针:正确而灵活地运用指针:n n可以有效的表示复杂的数据结构;可以有效的表示复杂的数据结构;n n能动态分配内存;能动态分配内存;n n能方便的使用字符串;能方便的使用字符串;n n方便有效的使用数组;方便有效的使用数组;n n在调用函数时可以得到多于一个的值

2、;在调用函数时可以得到多于一个的值;n n能直接处理内存地址能直接处理内存地址n n掌握指针的应用,可以使程序简洁、紧凑、高效掌握指针的应用,可以使程序简洁、紧凑、高效指针的概念指针的概念n n简单理解,指针就是简单理解,指针就是地址地址地址地址n n有变量的、数组的、函数的、字符串的有变量的、数组的、函数的、字符串的指针等,其实就是指针等,其实就是从某个地址开始的内从某个地址开始的内存,以何种方式解读存,以何种方式解读而已而已n n内存的访问方式内存的访问方式内存的访问方式内存的访问方式n n直接访问直接访问直接访问直接访问n n如如如如:i=2, j=6, k=9 i=2, j=6, k=

3、9 通过变量名通过变量名i i、j j、k k 来访问存来访问存储单元。储单元。n n间接访问间接访问间接访问间接访问n n如变量如变量 i i,不知道其值及地址,而只知道它的地不知道其值及地址,而只知道它的地址放在址放在30083008、30093009、30103010、30113011中,因此可通过中,因此可通过存放地址的单元找到变量存放地址的单元找到变量 i i 的值,此为间接访问。的值,此为间接访问。n n对间接访问,可定义一变量存放地址,如定义对间接访问,可定义一变量存放地址,如定义 i-pointer, i-pointer, 赋值赋值 i-pointer=&ii-pointer=

4、&i2000200420083008ijki_p 3 6 92000 : : : 内存用户数据区:指针的概念指针的概念指针的概念(续)指针的概念(续)n n例子:打开一个寝室门的两种办法n n将寝室钥匙带在身上,需要时直接找出该钥匙将寝室钥匙带在身上,需要时直接找出该钥匙打开寝室门直接访问打开寝室门直接访问n n将钥匙放在楼下管理员那里,需要时先找到管将钥匙放在楼下管理员那里,需要时先找到管理员理员,从管理员那里拿到钥匙,再打开寝室门从管理员那里拿到钥匙,再打开寝室门间接访问间接访问n n一个变量的地址称为该变量的“指针”。n n存放地址的变量叫“指针变量”。换句话说,指针变量存放地址。变量的

5、指针和指针变量变量的指针和指针变量n n变量的指针就是变量的地址。为了表示指针变量变量的指针就是变量的地址。为了表示指针变量和它指向的变量之间的联系,用和它指向的变量之间的联系,用* *符号表示指向符号表示指向n n指针变量的定义指针变量的定义n n类型标识符类型标识符* * 变量名;变量名;n n等价于:类型标识符等价于:类型标识符 * *变量名变量名; ;n n变量名前面的变量名前面的”*”*”表示该变量为指针变量,表示该变量为指针变量, 意意为为“ “指向指向指向指向.的指针的指针的指针的指针” ”,但指针变量名本身不包,但指针变量名本身不包含含* *n n指针变量有确定的指向的数据类型

6、指针变量有确定的指向的数据类型n n一个指针变量只能指向同一个类型的变量一个指针变量只能指向同一个类型的变量指针变量的引用指针变量的引用n n指针变量中只能存放地址,不要将一个整型量赋给一个指针变量(取用内容,结果无法预期)n n两个有关的运算符n n&:取地址运算符:取地址运算符n n* *:指针运算符(或称间接访问运算符):指针运算符(或称间接访问运算符)n n给指针变量赋值:n n赋给变量的地址:赋给变量的地址:intint* i; a = 9; i = &a;* i; a = 9; i = &a;20009i *ia2000指针变量的引用指针变量的引用n n用指针变量对变量赋值n ni

7、ntint i, j, *p; i, j, *p;p=&i; *p=3; j=*p+2;p=&i; *p=3; j=*p+2;n n“ “p=&ip=&i” ”的意义为指针变量的意义为指针变量p p指向变量指向变量 i i 。n n注意:注意:p p是地址变量,而是地址变量,而* *p p 是非地址变量,与是非地址变量,与i i是一回事。是一回事。n n“ “* *” ”:为指针运算符或叫指向运算符、间接运:为指针运算符或叫指向运算符、间接运算符,为单目运算符。算符,为单目运算符。指针变量的引用指针变量的引用n nint i, j, *p;p=&i; *p=3; j=*p+2;定义后p=&i后

8、*p=3后ijp:100010041008ijp100010041008ijp100010041008ijp1000 31000100010041008j=*p+2后 3 51000对对&和和*运算符的说明运算符的说明n n结合性:自右向左结合性:自右向左n nintint a, b, *p1, *p2; a, b, *p1, *p2;p1 = &a; p2 = &b;p1 = &a; p2 = &b;n n&*p1 &*p1 相当于相当于 &(*&(*p1) p1) 等于等于 &(* &(*p1)=&(a)=&a=p1p1)=&(a)=&a=p1n n*&a *&a 相当于相当于 * *(&

9、(&a) a) 等于等于 * *( (&a)=*(p1)=*p1=aa)=*(p1)=*p1=an n自增和自减自增和自减n nintint a,b,*p; a,b,*p; p=&a; a=3; b=5; p=&a; a=3; b=5;n n(*p)+; (*p)+; 相当于相当于 a+ a+ ,4 = a4 = an n*p+; *p+; 相当于相当于 *( *(p+) p+) 若若p p为为1000, 1000, 则则p+p+为为10041004数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量n n一个数组包含若干元素,每个数组元素都在内存中占用存贮单元,他们都有相应的地址。n

10、 n指针变量也可以指向数组和数组元素n n数组的指针是数组的起始地址n n数组元素的指针是数组元素的地址指向数组元素的指针变量的定义与赋值指向数组元素的指针变量的定义与赋值n n这种指针变量的定义和指向变量的指针变量相同这种指针变量的定义和指向变量的指针变量相同n nint int a10; a10; intint *p; p = &a0; *p; p = &a0;n n把把a0a0元素的地址赋给指针变量元素的地址赋给指针变量p p。p p指向指向a a数组的第数组的第0 0号号元素元素n nC C语言规定数组名代表数组的首地址,因此语言规定数组名代表数组的首地址,因此p = p = &a0;

11、&a0;等价于等价于p = a;p = a;n n注意数组注意数组a a不代表整个数组,上式的作用是把数组不代表整个数组,上式的作用是把数组a a的首地址赋给指针变量的首地址赋给指针变量p p,而不是把数组而不是把数组a a的各元的各元素的值赋给素的值赋给p p。通过指针引用数组元素通过指针引用数组元素n n通过指针引用数组元素可以提高目标程序质量通过指针引用数组元素可以提高目标程序质量(占内存少,运行速度快)(占内存少,运行速度快)n n假设假设p p被定义为指针变量,并已被赋了一个地址,被定义为指针变量,并已被赋了一个地址,使它指向某一个数组元素。如果有使它指向某一个数组元素。如果有* *

12、p = 1;p = 1;表示对表示对p p当前所指向的数组元素赋以一个值当前所指向的数组元素赋以一个值n n规定,规定,p+1p+1指向数组的下一个元素。例如,数组元指向数组的下一个元素。例如,数组元素是实型,每个元素占素是实型,每个元素占4 4个字节,则个字节,则p+1p+1意味着使意味着使p p的原值加的原值加4 4个字节,以使它指向下一个元素个字节,以使它指向下一个元素通过指针引用数组元素通过指针引用数组元素n n如果p的初值为&a0n np+i和a+i就是ai的地址,或者说,他们指向a数组的第i个元素n n*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即ain n指向数组

13、的指针变量也可以带下标,如pi与*(p+i)等价a0a1a2a3a ia7a8a9p, ( 2000) p+1,a+1p+2,a+2p+3,a+3p+i,a+ip+7,a+7p+8,a+8p+9,a+91234890A数组引用数组元素引用数组元素void main(void)void main(void) intint a10; a10;intint i; i;for (i=0; i10; i+)for (i=0; i10; i+) scanfscanf(%d,&ai(%d,&ai); ); printfprintf(n);(n);for (i=0; i10; i+)for (i=0; i10

14、; i+) printfprintf(%d,ai);(%d,ai); void main(void)void main(void) intint a10; a10;intint i; i;for (i=0; i10; i+)for (i=0; i10; i+) scanfscanf(%d,&ai);(%d,&ai); printfprintf(n);(n);for (i=0; i10; i+)for (i=0; i10; i+) printfprintf(%d,*(a+i)(%d,*(a+i); ; void main(void)void main(void) intint a10; a10;

15、intint i; i;for (i=0; i10; i+)for (i=0; i10; i+) scanfscanf(%d,&ai);(%d,&ai); printfprintf(n);(n);for (p=a; p(a+10); for (p=a; p(a+10); p+)p+) printfprintf(%d,*p);(%d,*p); 引用数组元素引用数组元素n n第1、2种方法执行效率相同。C编译系统是将ai转换为*(a+i)处理的。即先计算元素地址,所以费时比较多n n第3种方法比1、2快,用指针变量直接指向元素,不必每次都重新计算地址,象p+这样的自加操作较快,能提高效率n n用下

16、标法比较直观,能直接知道是第几个元素。而地址法或指针变量的方法不直观指针的基本操作指针的基本操作n n赋值n n把一个地址赋值给指针,通常是用数组名或者把一个地址赋值给指针,通常是用数组名或者地址运算符地址运算符&来进行地址赋值来进行地址赋值n n地址应该和指针类型兼容,即不能把一个地址应该和指针类型兼容,即不能把一个doubledouble类型的地址赋值给一个指向类型的地址赋值给一个指向intint类型的指类型的指针针指针的基本操作指针的基本操作n n求值/取值n n运算符运算符* *可取出指针指向地址中储存的数值可取出指针指向地址中储存的数值指针的基本操作指针的基本操作n n取指针地址n

17、n指针变量同其他变量一样具有地址和数值指针变量同其他变量一样具有地址和数值n n使用运算符使用运算符&可以得到存储指针本身的地址可以得到存储指针本身的地址n n上例中,上例中,ptr1ptr1被存储在内存中的被存储在内存中的0 0x0012ff34x0012ff34中,中,该内存单元的内容是该内存单元的内容是0 0x0012ff38x0012ff38,即即urnurn的地址的地址指针的基本操作指针的基本操作n n将一个整数加(减)给指针n n用用+ +运算符把一个整数加给指针,或者把一个运算符把一个整数加给指针,或者把一个指针加给一个正数指针加给一个正数n n整个整数和指针所指类型的字节数相乘

18、,然后整个整数和指针所指类型的字节数相乘,然后将所得的结果加到初始地址上将所得的结果加到初始地址上指针的基本操作指针的基本操作n n增加指针的值(减少)n n通过一般的加法运动或增量运算符来增加一个通过一般的加法运动或增量运算符来增加一个指针的值指针的值n n对指向某数组元对指向某数组元素的指针作增量素的指针作增量运算,可以让指运算,可以让指针指向数组的下针指向数组的下一个元素一个元素指针的基本操作指针的基本操作n n求差值n n求出两个指针的差值。通常对分别指向同一个求出两个指针的差值。通常对分别指向同一个数组内的两个元素的指针求差值,以求出元素数组内的两个元素的指针求差值,以求出元素之间的

19、距离之间的距离n n差值的单位是对应类型的大小,而不是字节数差值的单位是对应类型的大小,而不是字节数n n指向不同数组的指针之间的差值运算可能会得指向不同数组的指针之间的差值运算可能会得到一个数值结果,也可能导致一个运行时的错到一个数值结果,也可能导致一个运行时的错误误指针的基本操作指针的基本操作指针操作的注意点指针操作的注意点n n指针变量可以实现使本身的值改变n n如如p+p+使得使得p p的值不断改变,这是合法的,如果的值不断改变,这是合法的,如果不是用不是用p p而是而是a a变化(如用变化(如用a+a+)是不行的。因为是不行的。因为a a是数组名,其值在程序运行期间是固定不变的,是数

20、组名,其值在程序运行期间是固定不变的,是常量。是常量。n n要注意指针变量的当前值,防止产生指针越界指向多维数组的指针和指针变量指向多维数组的指针和指针变量n n假设有一个二维数组a341 13 35 57 79 91111 1313 15151717 1919 2121 2323a0a0 a1a1 a2a2 a200020001 1200420043 3200820085 5201220127 7201620169 9202020201111202420241313202820281515203220321717203620361919204020402121204420442323a200

21、0a12016a+22032指向多维数组的指针和指针变量指向多维数组的指针和指针变量表示形式表示形式含义含义地址地址a a二维数组名,数组首二维数组名,数组首地址地址20002000a0a0,*(a+0)*(a+0),*a*a第第0 0行第行第0 0列列元素地址元素地址 20002000a+1a+1第第1 1行首地址行首地址20162016a1a1,*(a+1)*(a+1)第第1 1行第行第0 0列列元素地址元素地址 20162016a1+2a1+2,*(a+1)+2*(a+1)+2,&a12&a12第第1 1行第行第2 2列元素地址列元素地址 20242024*(a1+2)*(a1+2),*

22、(*(a+1)+2)*(*(a+1)+2),a12a12第第1 1行第行第2 2列元素的值列元素的值 1313多维数组的指针多维数组的指针n n指向数组元素的指针变量指向数组元素的指针变量n n要找到数组中的要找到数组中的i i行行j j列元素,只要利用公式列元素,只要利用公式i*m+ji*m+j就可以计算出就可以计算出aijaij相对于数组开头的位置相对于数组开头的位置void main(void)void main(void) static static intint a34 = 1,3,5,7,9,11,13,15,17,19,21,23; a34 = 1,3,5,7,9,11,13,1

23、5,17,19,21,23;intint *p; *p;for(p=a0;pa0+12;p+)for(p=a0;pa0+12;p+) if(0 = (p-a0)%4)if(0 = (p-a0)%4) printfprintf(n);(n); printf(%4d,*p);printf(%4d,*p); 多维数组的指针多维数组的指针n n指向由m个整数组成的一维数组的指针变量n n使使p p不是指向整型变量,而是指向一个包含不是指向整型变量,而是指向一个包含mm个元素的个元素的一维数组一维数组void main(void)void main(void) static static intint

24、a34 = 1,3,5,7,9,11,13,15,17,19,21,23; a34 = 1,3,5,7,9,11,13,15,17,19,21,23;intint (*p)4, i, j; (*p)4, i, j;p = a;p = a;scanfscanf(“i = %d, j = %d”, &i, &j);(“i = %d, j = %d”, &i, &j);printfprintf(“a%d,%d = %dn”, I, j, *(*(p+i)+j);(“a%d,%d = %dn”, I, j, *(*(p+i)+j); 指针数组和指向指针的指针指针数组和指向指针的指针n n一个数组,其所

25、有元素都是指针类型的数据,称为指针数组n n类型名类型名 * *数组名数组名 数组长度数组长度 n nintint* p4;* p4;n n不要写成不要写成intint (*p)4 (*p)4;指向指针的指针指向指针的指针n n指向指针类型数据的指针变量void main( void)void main( void) char* name = ;char* name = ; char* p; char* p; intint i; i; for(i = 0; i5; i+) for(i = 0; i5; i+) p = name+i; p = name+i; printfprintf(“%s”,

26、*p);(“%s”,*p); void main(void)void main(void) char name = ; char name = ; char* p; char* p; intint i; i; for(i = 0; i5; i+) for(i = 0; i5; i+) p = name+i; p = name+i; printfprintf(“%s”,*p);(“%s”,*p); 指针变量作为函数参数指针变量作为函数参数n n函数的参数不仅可以是整型、实型、字符型数据,还可以是指针类型。其作用是将一个变量的地址传送到另一个函数中n n函数参数传递的实质:n nC C语言中,实参

27、变量和形参变量之间的数据传语言中,实参变量和形参变量之间的数据传递是单向的值传递方式递是单向的值传递方式n n指针变量作为函数的参数也要遵循这一规律。指针变量作为函数的参数也要遵循这一规律。调用函数不能改变实参指针变量的值,但可以调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值(间接性)改变实参指针变量所指向的变量的值(间接性)指针变量作为函数参数指针变量作为函数参数void swap(void swap(intint *p1, *p1, intint *p2)*p2) intint temp = 0; temp = 0;temp = *p1;temp = *p1; *

28、p1 = *p2; *p1 = *p2; *p2 = temp; *p2 = temp; void swap(void swap(intint p1, p1, intint p2) p2) intint temp = 0; temp = 0;temp = p1;temp = p1; p1 = p2; p1 = p2; p2 = temp; p2 = temp; void swap(void swap(intint *p1, *p1, intint *p2)*p2) intint *temp; *temp;temp = p1;temp = p1; p1 = p2; p1 = p2; p2 = t

29、emp; p2 = temp; void swap(void swap(intint *p1, *p1, intint *p2)*p2) intint *temp; *temp;*temp = *p1;*temp = *p1; *p1 = *p2; *p1 = *p2; *p2 = *temp; *p2 = *temp; 例:两数交换例:两数交换数组名作函数参数数组名作函数参数n n数组名可以用作函数的形参和实参n n数组名代表数组首地址。用数组名作实参,在调用函数时实际上是把数组的首地址传给形参,这样实参数组和形参数组共占同一段内存n n在调用函数后,实参数组的元素值可能会发生改变,这种值的

30、变化实际上是由形参和实参数组共享同一段内存而造成的。数组名作函数参数数组名作函数参数n n一个实参数组,想要在函数中改变数组的元素的值,实参与形参的对应关系:形参形参形参形参实参实参实参实参数组名数组名数组名数组名指针变量指针变量数组名数组名数组名数组名指针变量指针变量指针变量指针变量指针变量指针变量多维数组的指针作函数参数多维数组的指针作函数参数n n一维数组的地址可以作为函数参数传递,多维数组的地址也可以作为函数参数传递n n在用指针变量作形参以接受实参数组名传递来的地址时n n用指向变量的指针变量用指向变量的指针变量n n用指向一维数组的指针变量用指向一维数组的指针变量返回指针值的函数返

31、回指针值的函数n n一个函数可以带回指针型的数据n n函数的一般定义n n类型名类型名* * 函数名(参数列表)函数名(参数列表)n nintint* a(* a(intint x, x, intint y) y)n n在*a的两侧没有括弧,()的优先级高于*,因此a先和()结合n n最前面的int表示返回的指针指向整型变量函数的指针和指向函数的指针变量函数的指针和指向函数的指针变量n n一个函数在编译时被分配给一个入口地址。这个入口地址就被称为函数的指针n n可以用一个指针变量指向函数,然后通过该指针变量调用此函数intint max( max(intint i, i, intint j);

32、 j);void main(void)void main(void) intint (*p)( (*p)(intint, , intint); ); p = max; p = max; intint j = (*p)(2,3); j = (*p)(2,3); 指向函数的指针指向函数的指针n n指向函数的指针变量的一般定义形式n n数据类型数据类型 (*(*指针变量名指针变量名)( )(形式参数表形式参数表 ) )n n函数的调用可以通过函数名调用,也可以通过函数指针调用n n(*p)( )表示定义一个指向函数的指针变量,他不是固定指向哪一个函数的,而只是表示了一个存放函数入口地址的变量指向函数

33、的指针指向函数的指针n n在给函数指针变量赋值时,只需要给出函数名而不必给出函数的参数,不能写成p = max(a,b)的形式n n用函数指针变量调用函数时,只需要将(*p)代替函数名就可以了,在(*p)之后的括弧中按需要写上实参n n对指向函数的指针变量,p+n,p+等运算是没有意义的用指向函数的指针作为函数的参数用指向函数的指针作为函数的参数n n函数指针变量常用的用途之一就是把指针参数作为参数传递到其他函数void sub(void sub(intint (*a)(), (*a)(), intint (*b)()(*b)() intint a,b; a,b; intint i,j; i,

34、j; a = (*a)(i); a = (*a)(i); b = (*b)(i,j); b = (*b)(i,j); 字符串的指针和字符串的指针和指向字符串的指针变量指向字符串的指针变量n n字符串的表示形式n n用字符数组实现用字符数组实现n nstatic char string = “I love china”static char string = “I love china”;n n用字符指针实现用字符指针实现n nchar *string = “I love china”char *string = “I love china”;n nC语言对字符串常量是按字符数组处理的,实际上在

35、内存中开辟了一个字符数组用来存放字符串常量。在程序中定义一个字符指针变量string,并把字符串首地址赋给它字符串指针作函数参数字符串指针作函数参数n n用字符数组作参数n nvoid copy_string(char void copy_string(char from, char to)from, char to) intint i = 0; i = 0;while(0 != fromi)while(0 != fromi) toi = from i;toi = from i;i+;i+; toi = 0;toi = 0; n n形参用字符指针变量n nvoid copy_string(ch

36、ar *from, char void copy_string(char *from, char *to)*to) for( ; 0 != *from; from+,to+) for( ; 0 != *from; from+,to+) *to = *from;*to = *from; *to = 0;*to = 0; 字符串指针作函数参数字符串指针作函数参数n n对copy_string函数的简化n nwhile(0 != (*to = *from)while(0 != (*to = *from) to+; from+;to+; from+; n nwhile(0 != (*to+ = *fr

37、om+)while(0 != (*to+ = *from+)n nwhile(*to+ = *from+)while(*to+ = *from+)字符指针变量与字符数组字符指针变量与字符数组n n字符数组由若干个元素组成,每个元素中放一个字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址,决不是字符,而字符指针变量中存放的是地址,决不是将字符串放到指针变量中将字符串放到指针变量中n n对数组赋初值要用对数组赋初值要用staticstatic存储类别,对字符指针变存储类别,对字符指针变量不必加量不必加staticstaticn n在定义一个数组时,在编译时已经分配内存单

38、元,在定义一个数组时,在编译时已经分配内存单元,有确定的地址。而定义一个字符指针变量时,给有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个地址指针变量分配内存单元,在其中可以放一个地址值,如果未对它赋一个地址值,则其指向的地址值,如果未对它赋一个地址值,则其指向的地址不定不定字符指针变量和字符数组字符指针变量和字符数组正确正确正确正确错误错误错误错误char* a;char* a;a = “I love china!”;a = “I love china!”;char str14;char str14;strstr = “I love = “I love china!”china!”char* a;char* a;a = “I love china!”;a = “I love china!”;char str14;char str14;strstr = “I love = “I love china!”;china!”;

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 幼儿/小学教育 > 幼儿教育

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号