1 / 99

第八章 指 针

第八章 指 针. 指针在 C 语言里应用极为广泛,如 内存的 动态分配 、 内存地址的直接处理 、 函数调用时 批量参数的传递以及复杂数据结构的简洁表达 等许多其它数据类型难以实现的复杂操作。 在这一章里,主要介绍 指针的概念 、 指针 的定义与运算、指针与数组 、指针数组 等项内 容。. 8.1 指针与指针变量的概念. 一、什么是指针 1 、直接存取 2 、间接存取. 二、指针变量. 8.2 指针变量的定义和引用. 一、指针变量的定义. 二、指针变量的使用规则. 三、指针的指针. 四、指针的用途

mandek
Download Presentation

第八章 指 针

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第八章 指 针 指针在C 语言里应用极为广泛,如内存的 动态分配 、内存地址的直接处理、函数调用时 批量参数的传递以及复杂数据结构的简洁表达 等许多其它数据类型难以实现的复杂操作。 在这一章里,主要介绍指针的概念、指针 的定义与运算、指针与数组、指针数组等项内 容。

  2. 8.1 指针与指针变量的概念 一、什么是指针 1、直接存取 2、间接存取 二、指针变量 8.2 指针变量的定义和引用 一、指针变量的定义 二、指针变量的使用规则 三、指针的指针 四、指针的用途 1、动态分配函数 malloc() 2、动态释放函数 free() 3、计算字节数函数sizeof()

  3. 8.3 指针与数组 一、指向一维数组的指针变量 二、利用数组名引用一维数组 三、利用数组名引用二维数组 四、通过一维数组引用二维数组 五、通过行指针引用二维数组 六、指针数组 七、指向字符串的指针变量 8.4 指针与函数 一、数组名与指针变量作函数参数 1、形参和实参都为数组名 2、形参和实参都为指针变量 2、实参为数组名,形参为指针变量 3、实参为指针变量, 形参为数组名

  4. 二、行指针变量作函数参数 三、行指针变量作函数参数 四、指向函数的指针变量 五、返回指针值的函数 六、字符串指针变量作为函数参数

  5. 么 是 指 针 “指针”是个地址的概念,它本身不 是变量,并不分配存储单元,仅表示对 象在内存中的地址。也就是说,一个变 量在内存空间中所占用的地址称为 该变量的指针。 8.1 指针与指针变量的概念 指针与指针变量是两个有着密切联系的不同概念 下面将分别对它们进行介绍。 一、什么是指针

  6. a 2000 变量的 指针

  7. 2001 a p main() { int a, b; float x; 2000 a 2003 2005 2007 x b 5 2004 2002 2006 2000 a=5; b=6; x=2.0; printf(“a=%d, b=%d, x=%f\n”, a,b,x); } a x b 直 间 接 接 存 存 取 取 5 6 2.0 0000 0000 0000 0000 0000 0000 0000 0010 0000 0000 0000 0110 0000 0000 0000 0101 p & a = 2000

  8. 针 变 量 p a 2000 二、指针变量 如果一个变量是专门用来 存放其它变量的地址,那么就 称这个变量为指针变量。 指针变量 2000 1001

  9. a p b 8.2 指针变量的定义和引用 指针型说明符 数据类型 *指针变量名 格式: 200 int a, b,*p 2000 100 2000 p=&a; *p=100; 2002 p=&b; *p=200; p=&a;

  10. a 100, 200 b p1 取址符号 取值符号 100 p=&a; *p=200; 200 p2 main() { int a, b, *p1, *p2; p1=&a; p2=&b; *p1=100; *p2=200; } printf(“a=%d, b=%d\n”, a,b;); printf(“a=%d, b=%d\n”, *p1,*p2); 100, 200

  11. 指针变量的使用规则 p1 a b p2 p1=(int *)b; 1、指针变量中的值只能是指针(即对象变量的地址),不能为其它内容。 例如,int a, b, *p1, *p2; p1=&a; 100 p1=100; *p1=100; p2=p1; 2、一般情况下,一个指针变量只能指向同一个类型的指针。 强制类型转换 例如,int a, *p1 ; float b ; p1=&b;

  12. p1 p1 a 3、指针变量在使用之前必须赋初值 int a, *p1; p1= &a; 或int a, *p1= &a; 4、如有定义: int a=0, *p1 ; p1= &a ; (*p1)++ ; 相当于a++ ; 1 若写成: *p1++ ; 0 5、指针变量本身也在内存中占用存储单元 1094

  13. p1 a s b p2 main() { int a, b, s,*p1, *p2; p1=&a; p2=&b; *p1=100; *p2=200; s=*p1+*p2; printf(“s=%d \n”, s); } 100 300 200

  14. a 100 p2 p 200 交 换 地 址 p1 b 请利用指针变量,实现a与b两个变量中的数据按从大小顺序输出。 举例 main() { int a=100, b=200, *p1,*p2,*p; p1=&a ; p2=&b ; if (a < b) { p=p1; p1=p2; p2=p; } printf(“%d,%d\n”,*p1,*p2); } 200, 100

  15. a c 交 换 数 值 b p1 p2 main() { int a=100, b=200, *p1,*p2,c; p1=&a; p2=&b; if (a<b) { c=*p1; *p1=*p2; *p2=c; } printf(“%d, %d\n”, a,b); } if (*p1<*p2) 100 100 200

  16. 练习 请利用指针变量,输出 a、b 两个变量中最大的数据。 main() { int a , b , max, *p1=&a, *p2=&b; scanf(“%d,%d”, p1,p2) ; if (*p1>*p2) max=*p1; else max=*p2; printf(“max=%d\n”, max); }

  17. 针 的 指 针 当指针指向的对象是另一个指针 变量时就构成了指针的指针。而指针 的指针则是多级指针最简单最常用的 一种形式(通常也称为多级间接寻址)。 p1 p2 p3 a FFD6 FFD4 FFD2 FFD8 FFD4 FFD6 FFD2

  18. p1 p2 p3 a FFD6 FFD4 FFD2 FFD4 FFD6 FFD8 FFD2 100 int a, ***p3; *p1, **p2, p1=&a; 200 p2=&p1; p3=&p2; ***p3 *p1=100; 300 **p2=200; ***p3=300; **p2 printf(“%d\n”, ); *p1

  19. 针 的 用 途 指针的用途之一就是可以实现内存的动态分配。 在C程序中,如果我们定义了某个变量或数组,编 译系统就会给它分配存储空间。即使该变量或数组 在其应用后的程序中不再使用,那么它所占用的存 储空间也不能另作他用,象这样的内存空间分配被 称作为内存的静态分配。 为了更有效地利用内存空间,则可采用指针对 内存进行动态分配(即需要时开辟空间,结束时再释 放空间)。

  20. 07B6 07B7 p 内 存 动 态 函 数 1、分配函数 格式:malloc(size) 功能:请求分配连续size个存储位置的区域。 说明: size 表示是申请内存的字节数量。 例如: int *p ; p=malloc(2); *p=100 ;

  21. s t u d e n t \0 p 2、释放内存函数 格式:free(指针变量) 功能:将由malloc函数分配的存储单元释放出来。 main() { int *p ; p=malloc(8); strcpy(p, “student”); printf(“%s”, p); free(p) ; }

  22. 3、计算字节数量函数 格式:sizeof (数据类型标识符) 功能:其函数值为该类型变量在内存中所占的字节数。 main() { int a, b[10] ; float c[6] ; printf(“%d\n”, ); sizeof(int) 2 printf(“%d\n”, sizeof(a)); 2 printf(“%d\n”, sizeof(b)); 20 printf(“%d\n”, sizeof(c)); } 24

  23. 针 与 数 组 指针和数组有着密切的关系。 数组是由同一类型变量组成的有序集合,其本身存储的是 各种类型的数据。而指针则是专门用来存放其它变量地址的变 量。 从前面的内容得知,当一个指针变量存有某一个变量的地 址时,则这个指针就指向该变量。而在C 语言中规定利用指针 还可以对数组进行操作。 8.3 指针与数组

  24. p 一、指向一维数组的指针变量 int a[8]={2,4,6,8,10,12,14,16}; int i; for(i=0;i< 8;i++) printf(“%d,”, a[i]); a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]

  25. 4 6 p … … 2 int *p; printf(“%d,”,*p); p=&a[0]; p=a; printf(“%d,”,*p); p++ ; printf(“%d,”,*p); p++ ; a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]

  26. main() { int a[8]={2,4,6,8,10,12,14,16}, i , *p; p int *p; for(p=a, i=0; i< 8; i++) { printf(“%d,”,*p); p=a; p++ ; } 2 } a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] 4 6

  27. p main() { int a[8]={2,4,6,8,10,12,14,16}, i, *p; for(p=a; p<a+8; p++) printf(“%d,”, *p); } a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]

  28. 关于指针变量的运算 1、p++ (或p+=1) 使p指向下一个元素的地址。 2、若有*p++ 由于++ 和 * 同优先级,其结合方向为 自右而左,因此它等价于 *(p++)。 main() { int a[8]={2,4,6,8,10,12,14,16}, i, *p; for(p=a, i=0; i<8; i++) printf(“%d,”, *p++); } 3、*(p++)与 *(++p) 作用不同。 前者是先取*p 的值后使 p加1; 后者是先使 p加1,再 读取 *p 的值。

  29. p p p 3、*(p++)与 *(++p) 作用不同。前者是先取*p的值 后使 p 加1; 后者是先使 p 加1,再取 *p。 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] *(p++) 2 *(++p) 4 *(++p)与*++p 等价 4、(*p)++表示是 p 所指向的元素值加 1。 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] 5 (*p)++ 3 4

  30. p 5、若有以下操作,则有: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] *(p--) 5 3 *(++p) 6 *(--p) 3

  31. p A) p+=2, *(p++) B) p+=2, *++p C) p+=3, *p++ D) p+=2, ++*p 若有以下定义,则其值为 3 的表达式是: 练习 int a[ ]={1,2,3,4,5,6,7,8}, *p; p=a; a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]

  32. p A) 0,5 C) 0,6 B) 1,5 D) 1,6 以下程序的输出结果是: 练习 main() { int a[ ]={1,2,3,4,5,6}, *p; p=a; *(p+3)+=2; printf(“%d,%d\n”, *p, *(p+3)); } a[0] a[1] a[2] a[3] a[4] a[5] 6

  33. 二、利用数组名引用一维数组 a[0] a[1] a[2] a[3] a[4] a a+1 a+2 a+3 a+4 *(a+1) *(a+2) *(a+3) *(a+4) *a main() { int a[ ], i, ; for(i=0; i<5; i++) scanf(“%d”, a+i ); for(i=0; i<5; i++) printf(“%d,”, *(a+i) ); } 2 ,4 ,6 ,8 ,10

  34. 三、利用数组名引用二维数组 int a[3][3]={2,4,6,8,10,12,14,16,18}; main() { int a[3][3]={2,4,6,8,10, 12,14,16,18}; int i, j; for(i=0; i<3; i++) printf(“%p,”, a+i); } a a+1 a+2 a+i 2000 ,2006 ,200C 代表a 数组中 第i行首列的地址 2 8 14 *(*(a+i))

  35. *(a+0)+0 *(a+0)+1 *(a+0)+2 a+0 a+0 *(a+1)+0 *(a+1)+1 *(a+1)+2 a+1 a+1 *(a+2)+0 *(a+2)+1 *(a+2)+2 a+2 a+2 代表a 数组中 第i行首列的地址 … … for(i=0; i<3; i++) { for(j=0; j<3; j++) printf(“%p,”, *(a+i)+j); printf(“\n”); } a+i *(a+i)+j 代表a 数组中 第i行j列的地址 2 8 14 *(*(a+i))

  36. a+0 a+1 a+2 *(a+i) … … for(i=0; i<3; i++) { for(j=0; j<3; j++) printf(“%p,”, *(a+i)+j); printf(“\n”); } 代表a 数组中 第i行首列的地址 代表a 数组中 第i行j列的地址 a+i *(a+i)+j *(*(a+i)) *(*(a+i)+j) 代表a 数组中 第i行首列的元素值 代表a 数组中 第i行第j列的元素值

  37. a+0 a+1 a+2 2 8 14 … … int a[3][3]={ 2,4,6,8,10,12, 14,16,18 }, i, j ; for(i=0; i<3; i++) { printf (“%d”, *(*(a+i ))); printf (“\n”); } }

  38. a+0 a+1 a+2 2 4 6 8 10 12 14 16 18 … … for(i=0; i<3; i++) { for(j=0; j<3; j++) printf (“%d,”, *(*(a+i) +j) ); printf (“\n”); }

  39. a[2]+0 a[0]+0 a[1]+0 a[2]+1 a[0]+1 a[1]+1 a[2]+2 a[1]+2 a[0]+2 四、通过一维数组引用二维数组 a[0] a[1] a[2] … … 代表a 数组中 第i行j列的地址 代表a 数组中 第i行首列的地址 a[i] a[i]+j *(a[i]) *(a[i]+j) 代表a 数组中 第i行首列的元素值 代表a 数组中 第i行j列的元素值

  40. 2 4 6 8 10 12 14 16 18 … … int a[3][3]={2,4,6,8,10,12, 14,16,18}, i, j ; for(i=0; i<3; i++) { printf (“%8p ”, a[i]+j); printf (“\n”); } FFC8 FFCA FFCC FFCE FFD0 FFD2 FFD4 FFD6 FFD8 … … for(i=0; i<3; i++) { for(j=0; j<3; j++) printf(“%d,”, *(a[i]+j)); printf(“\n”); }

  41. p p+1 p+2 六、指针数组 五、通过行指针引用二维数组 行指针 代表a 数组中 第i行首列的地址 代表a 数组中 第i行j列的地址 p+i (或*(p+i) ) *(p+i) +j *(*(p+i) ) *(*(p+i) +j ) … … 代表a 数组中 第i行首列的元素值 代表a 数组中 第i行j列的元素值

  42. 指 针 p p++ p++ 2, 4, 6 P有3个元素 数据类型 (*p)[3] … … int a[3][3]={2,4,6,8,10,12, 14,16,18}, i, j ; int (*p)[3]; p=a; for(i=0; i<3; i++, p++) { for(j=0; j<3; j++) printf(“%d,”, (*p)[j]); printf(“\n”); } … … 格式: 8, 10, 12 14, 16, 18

  43. p 2 4 6 8 10 12 14 16 18 … … int a[3][3]={2,4,6,8,10,12,14,16,18}, i, j ; int (*p)[3]; p=a; for(i=0; i<3; i++) { for(j=0; j<3; j++) printf(“%d,”, ); printf(“\n”); } … … *(*(p+i)+j))

  44. A) 2,3 B) 2,6 C) 3,3 D) 3,6 main() { static int a[3][3]={{2},{4},{6}}; int i, j , *p ; p=&a[0][0]; for(i=0; i<2; i++) { if (i= =0) a[i][i +1]=*p+1; else ++p ; printf(“%d,\n”, *p ); } } 练习

  45. p p main() { static int a[3][3]={{2},{4},{6}}; int i, j , *p ; p=&a[0][0]; for(i=0; i<2; i++) {if (i==0) a[i][i+1]=*p+1 else ++p ; printf(“%d,\n”, *p ); } } 3 2 , 3 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] 3

  46. A) 60 B) 68 C) 99 D) 108 main() { static int a[3][4]={1,3,5,7, 9,11,13,15, 17,19,21,23}; int i, j , (*p)[4] ,k=0; p=a; for(i =0; i <3; i ++) for(j =0; j <2; j ++) k+=*(*(p+i )+j) ; printf(“%d\n”, k ); } 练习

  47. 针 数 组 如果在一个数组中,若其中的所有元素均 为指针类型的数据,则称为指针数组。也就是 说,指针数组中的每一个元素都相当于一个指 针变量。 2000 2002 2004 六、通过指针数组引用数组元素 数组长度 数据类型 *数组名[n] 格式: int *p[3]; p[0]=&a[0]; p[1]=&a[1]; p[2]=&a[2];

  48. 针 数 组 用 途 它比较适合用来指向若干个字符串,使得对字符串的处理 更加灵活。 如,采用指针数组对字符串的查询、排序等,其主 要优点是, 它可以有效地利用内存的存储空间并且提高字符串 的查询和排序效率。 2000 2003 2007 2009 char *p[4]={“aa”, “bbb”, “c”, “dddd”}; main() { int i; for(i=0;i<4;i++) printf(“%c\n,”, *p[i] ); } printf(“%s,”, p[i]); aa bbb dddd c a ,b ,c ,d

  49. 1,3,5,7 2000 2002 2004 2006 举例 main() { int a[4]={1,3,5,7 }, *num[4], i ; for(i =0; i <4; i ++) num[i]=&a[i]; } for(i=0;i<4;i++) printf(“%d,”, *num[i]);

  50. 12 练习 main() { int a[12]={1,2,3,4,5,6,7,8,9,10,11,12},*p[4],i ; for(i=0; i<4; i++) p[i]=&a[i *3]; printf(“%d\n”,p[3][2]); } for(i=0;i<4;i++) printf(“%d,”, *p[i]); 1, 4, 7, 10

More Related