1 / 41

第 十 章 指 针

第 十 章 指 针. 一、内存单元的内容和内存单元的地址: 内存区域被划分成一个一个的内存单元,一个内存单元可 以存放一个字节的数据,每一个内存单元都有一个编号,统称 为地址。 例: int i=3 ; char j= ‘ s ’ ;. §10.1 指针的概念. 地址. 内存单元. 3. 2002 2004 3000. 2000 2001. 变量 i 变量 j. 编译时为变量 i 分配 2000 和 2001 两 个字节的内存单元 , 为 j 分配 2003 一个字节的内存单元. 75. 2003.

macha
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. 第 十 章 指 针

  2. 一、内存单元的内容和内存单元的地址: 内存区域被划分成一个一个的内存单元,一个内存单元可 以存放一个字节的数据,每一个内存单元都有一个编号,统称 为地址。 例:int i=3; char j=‘s’; §10.1 指针的概念 地址 内存单元 3 2002 2004 3000 2000 2001 变量i 变量j 编译时为变量i分配2000和2001两 个字节的内存单元,为j分配2003 一个字节的内存单元 75 2003 因为内存单元的地址就是“指向”了该内存单元,故通常把内存单元的地址称为指针。

  3. 直接访问:通过变量名访问。 char j=‘s’; printf(“%c”, j ); 间接访问:通过该变量的指针来访问。 p=&j; 称:指针变量p指向变量j,p是变量j的指针。 二.内存单元的访问: j 75 2000 p j 75 2000

  4. 变量的指针:是一个变量的地址, 是常量。 指针变量:是存放变量地址的变量,其 值是该变量的地址。 要引用指针,必须定义指针。 定义指针,是为了通过指针访问内存单元。 一个数组或函数占有一段连续内存单元,假如将一个数组或函数的首地址赋给指针变量,通过指针就可以找到该数组或函数。

  5. 一、指针变量的定义 类型标识符 * 标识符 例如:int *p “标识符”是指针变量名。 如 p “*”表示定义指针变量 “类型标识符”表示该指针变量所指向的变量类型。 指针指向一个变量的地址,用*表示指向。 §10.2 变量的指针

  6. 指针变量只能存放地址。 未经赋值的指针变量不能用。 C语言提供两种相关地址运算符: &: 取地址运算符 *: 取内容运算符 *和&的优先级相同。 例:int a=5,b; int *p; p=&a; b=*p; a , b &a 2000 p a &a 5 二、指针变量的引用 p 2000 5 2002 ... ... 3000 类型说明中的*表示 定义指针变量 表达式中的*是运算符 *p表示p指向地址里的值

  7. (1)、int a,*pa; pa=&a; (2)、int a=5,*p=&a; (3)、int a,*pa=&a,*pb; pb=pa; (4)、int a[5],*pa; pa=a; (5)、char *pc; pc=“c language”; 三、指针变量的赋值: /*整型变量a的地址赋给指针变量pa*/ /*指针变量p取得整型变量a的地址.*/ /*指针pa的值赋给指针pb*/ /*将数组a的首地址赋给相同类型的指针pa*/ /*将字符串的首地址赋给指针变量*/

  8. [例10.1] main () { int a,b; int *pointer_1, *pointer_2; /* 定义指针变量 */ a = 100; b = 10; pointer_1 = &a; pointer_2 = &b; printf("%d,%d\n", a,b ); printf("%d,%d\n", *pointer_1,*pointer_2 ); } 程序运行结果: pointer-1 a 100 &a 100,10 100,10 b pointer-2 10 &b

  9. [例10.2]输入a和b两个整数,按先大后小的顺序输出a和b。[例10.2]输入a和b两个整数,按先大后小的顺序输出a和b。 main () { int *p1, *p2, *p , a, b; scanf("%d,%d",&a,&b); p1 = &a; p2 = &b; if (a < b) { p = p1; p1 = p2; p2 = p; } printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n", *p1, *p2 ); } 运行:5,9 p1 a 5 &a p &b b p2 9 &b &a a=5,b=9; max=9,min=5 该例不交换变量a、b的值,而是交换指针p1、p2的值。

  10. [例10.3]题目要求同[例10.2],输入a和b两个整数,按先大后小的顺序输出a和b。[例10.3]题目要求同[例10.2],输入a和b两个整数,按先大后小的顺序输出a和b。 swap( int* p1,int *p2 ) /*交换指针p1、p2所指向的变量的值 */ { int p; p = *p1; *p1 = *p2; *p2 = p; } main () { int a, b; int *pointer_1, *pointer_2; scanf("%d,%d",&a,&b); pointer_1 = &a; pointer_2 = &b; if (a<b) swap(pointer_1, pointer_2) ; printf("\n%d,%d\n",a,b); } 四、指针变量作为函数的参数 把变量a和b的地址传送给形参

  11. 指针可以指向数组和数组元素,对数组元素的访问: 既可以使用数组下标,也可以使用指针。 一、指向数组元素的指针变量 指向数组元素的指针变量,其类型应与数组元素相 同。例1: int a[7]; int *p; p=&a[0]; 或 p=a; 例2: float b[10],*p=b ; 或 float b[10],p=&b[0]; 1 a[0] p &a[0] 2 3 4 5 6 a[6] 7 §10.3 数组的指针 /*指的是把数组a的首地址赋给指针p*/

  12. 设:int a[10],*p=&a[0]; (1).p+1和a+1都是指向下一个元素a[1]; 二、通过指针引用数组元素 如果数组元素是整型,p+1表示p的地址加2; 如果数组元素是实型,p+1表示p的地址加4; a表示数组首地址。 p+i 和a+i 指向元素a[i]。 (2).*(p+i) 访问元素a[i]; 例: *(p+5)和*(a+5) 与a[5]等效; (3).指向数组指针可以带下标: 例: p[i]与*(p+i)等效.

  13. 1、下标法 main () { int a[10]; int i; for(i=0;i<10;i++) scanf("%d", &a[i]); printf("\n"); for(i=0;i<10;i++) printf("%d ", a[i] ); } [例10.5] 输出数组的全部元素。(设10个整数) 特点:常用、过程简单直观

  14. 2、用数组名计算数组元素的地址。 main( ) { int a[10]; int i; for(i=0;i<10;i++) scanf("%d", &a[i]); printf("\n"); for(i=0;i<10;i++) printf("%d ", *(a+i) ); } 特点:不移动指针 但要计算每个元素的地址 费时间

  15. 3、用指针访问各元素。 main () { int a[10]; int *p , i; for(i=0;i<10;i++) scanf("%d", &a[i]); printf("\n"); for( p=a ; p<(a+10) ; p++ ) /* p++使p指向下一个元素 */ printf("%d ", *p ); } 特点:移动指针 速度快

  16. 例:通过以下程序输出a数组中的10个元素。 main() { int a[10],*p,i; p=a; for(i=0;i<10;i++) scanf("%d",p++); printf("\n"); for(i=0;i<10;i++,p++) printf("%d\t",*p); } ??试问:以上程序可以输出a数组中的 10个元素吗?

  17. main() { int array[10]; … f( array ,10); … } 三、数组名作函数参数 1、形参和实参都用数组名 f( int arr[],int n) { … }

  18. 2、实参用数组名,形参用指针变量。 main() { int array[10]; … f(array,10); … } f( int *arr,int n) { … }

  19. 3、实参、形参都用指针变量。 main() { int array[10],*p; p=array; … f(p,10); … } f( int *arr,int n) { … }

  20. 4、实参用指针变量,形参用数组名。 main() { int array[10],*p; p=array; … f(p,10); … } f( int arr[ ],int n) { … }

  21. 一、字符串的表现形式 C语言中,有两种方式可以实现字符串: 字符数组、字符指针。 [例10.16]:字符数组 main() { char string[ ] ={“How are you!”}; printf("%s\n",string); } §10.4 字符串的指针 用字符串对字符数组赋值 string是数组名,代表字符数组的首地址。 数组可以用下标访问,也可以用指针访问

  22. main() { char *name1 =”Mary"; char *name2=“Hare”; printf("%10s%10s\n",name1,name2); } Mary Hare name1 name2 [例10.17]字符指针 name1、name2是指针变量 char *name1 =“Mary”; 等价于: char * name1; name1 = “Mary”; 它把字符串常量的首地址赋给指针name1.

  23. main () { char a[ ] = "I am a boy."; char b[20]; int i; for (i=0; *(a+i) !='\0'; i++) *(b+i) = *(a+i); *(b+i) = '\0'; printf("string a is: %s\n",a); printf("string b is:"); for (i=0; b[i] !='\0'; i++) printf("%c",b[i]); printf("\n"); } 数组a 数组b a I b a m a b o y . \0 [例10.18] 将字符串a复制到字符串b。 用数组名计算数组元素的地址 特点:不移动指针

  24. main () { char a[ ] = "I am a boy.",b[20],*p1,*p2; int i; p1=a;p2=b; for ( ; *p1 !='\0'; p1++,p2++) *p2 = *p1; *p2 = '\0'; printf("string a is: %s\n",a); printf("string b is:"); for (i=0; b[i] !='\0'; i++) printf("%c",b[i]); printf("\n"); } 数组a 数组b p1 p2 I a m a b o y . \0 [例10.19]:用指针处理字串复制. 特点:移动指针

  25. 例10.21: main() { char *a=“I love china!”; a=a+7; printf(“%s”,a); } 运行结果如下: China! (a+7)是用指针指向数组元素a[i]的第7个字符

  26. 可以看到: 1、字符数组和字符指针的概念不同。 2、字符指针指向字符串,而C语言中, 字符串按数组方式处理,因此,字符指 针和字符数组的访问方式相同。

  27. 一、用函数指针变量调用函数 函数指针定义的一般形式: 函数返回值类型(*指针变量名)( ) 例: int (*p)( ) 说明:(*p)( ) 表示定义一个指向函数的指针变量, 它不固定指向哪一个函数,它是专门用来存放函数的入口 地址的,该函数返回一个整型值。 C规定:函数的名称就就代表函数的入口地址。 §10.5 函数指针

  28. 用函数名调用子函数max() int max(int x, int y); /*原型*/ {int z; if (x>y) z = x; else z = y; return z; } main () {int a,b,c; scanf("%d,%d", &a, &b); c = max(a, b); printf("a=%d,b=%d,max=%d",a,b,c); } [例9.23] 求a和b中的大者。

  29. 用函数指针调用函数max() int max(int x, int y) /*原型*/ {int z; if (x>y) z = x; else z = y; return z;} main () { int (*p) (int, int); /*定义函数指针p */ int a,b,c; p = max; /*函数max的入口地址赋给函数指针p*/ scanf("%d,%d", &a, &b); c = (*p)(a,b); /*用函数指针p调用函数 */ printf("a=%d,b=%d,max=%d",a,b,c); } [例9.23] 求a和b中的大者。 用函数指针变量调用函数时,只须将(*p)代替函数名max,并加上实参

  30. 一般形式: 类型标识符 * 函数名(参数表) 例、  int * a (int x, int y) 声明一个函数,函数名为a,其返回值类型是“指向整型 的指针”, 函数形式参数为int x 和 int y。 注意:在a的两侧分别为*运算符和( )运算符,a先与( ) 结合,这是函数形式;函数前有个*号,表示该函数为指针 型函数. §10.6 返回指针的函数(自学)

  31. 一、指针数组 概念:指针数组是一个数组,该数组中的 每一个元素均是指针变量。 形式:类型标识符 *数组名[数组元素个数] 例: int * p[4];   定义一个指针数组,数组名p,有4个元素, 每一个元 素是指向整型变量的指针。如: char *name[3]={”math”,”computer”,”ccm”}; 可用 puts(name[i]) 语句输出。 §10.7 指针数组和指向指针的指针(自学)

  32. 二、指向指针的指针 定义举例: char * * p; char *name[]={“Ann”,“Hare”,“Jack”}; p=name; p是一个指向指针的指针。 被p指向的指针指向字符变量。 p name[0] name[1] name[2] Ann Hare Jack name指针数组 二维字符数组

  33. main() { int i; char *name[]={"Ann","Hare","Jack","Mary"}; char **p; printf("\n Students's names are:\n"); for(i=0;i<4;i++) { p=name+i; printf("%6s\t",*p); } } 运行结果: Ann Hare Jack Mary name[0] name[1] name[2] Ann Hare Jack 程序举例: name指针数组 二维字符数组 p name[3] mary

  34. 一、有关指针的数据类型 定义: int i; 定义整型变量i int *p; p是指向整型数据的指针变量 int a[n]; 定义数组a,元素类型为int,元素个数是n int *p[n]; p是指针数组,包含n个指针,每一个指针可 以指向整型数据 int f(); f是函数,返回值是int int (*p)(); p是函数指针,所指向的函数返回整型数据 int *p(); p是函数,返回值是指针,该指针指向整型数据 int **p; p是指针,指向一个指向整型数据的指针 §10.8 指针使用小结

  35. 二、指针运算小结 1、指针变量加/减运算 p++、p--、p+i、p-i、p+=i、p-=i 加1表示指向下一个数据。 2、指针变量赋值 p = &a; 变量a的地址赋给p,即指针p指向a p = array; 数组array首地址赋给p p = &array[i]; 数组元素array[i]的地址赋给p p = max; 函数max的入口地址赋给p p1 = p2; 指针p2的值赋给指针p1, 即p1、p2所指的数据相同 p=NULL; 指针变量可以由空值,NULL的值为0

  36. 3、空指针 p = NULL 空指针p=NULL表示p不指向任何数据。 在stdio.h中,NULL被定义为0: #define NULL 0 习惯上,不使用 p = 0而使用 p = NULL 指针变量p可以与NULL作比较, 例:if (p = = NULL) ... 注意:空指针不指向任何数据,与p未赋值不同。 当p未赋值时,其值是不确定的,而空指针 的值是确定数0。

  37. 4、指针变量相减 当p1、p2指向同一个数组的元素,指针相减p2-p1等于p1、p2间的元素个数。 注意:指针相加无意义。 5、两个指针的比较 当p1、p2指向同一个数组的元素时可以比较,如:p1 > p2。表示p1在p2之后。若p1、p2不是指向 同一个数组的元素,比较无意义。

  38. 三、空类型指针 void void *p,表示p是空类型指针,它可以指向任何数据类型。 空类型指针与其他类型指针之间赋值时,应进行强制类型转换, 例、 char *p1; void *p2; p1 = (char *)p2; p2 = (void *)p1;

  39. 10.1 指针变量a所指的字符串长度为, 这个长度是可以用strlen(a)测出来的。 char *a=“\nMY Name is\”zhang li\”.\n”; (1)26 (2) 27 (3) 28 (4) 24 (5) 23 10.2 下面程序的作用是: 将两个变量中的值互换, 请检查程序是否正确,如不正确的,改正之。 main ( ) { int a=3,b=4; int *p1,*p2,*p; p1=&a;p2=&b; p=p1;p1=p2;p2=p; printf(“a= %d,b= %d\n”,a,b); } 第10 章 课堂练习

  40. 10.3已知p1和p2为指针变量, 且已指向同一个整 型数组中的元素,a是一个整型变量,问下面 哪一个语句不能正确执行? (1) a=*p1 (2) a=*p1+*p2 (3) a=*p1-*p2 (4) p1=a-p2 10.4 有一个二维数组a[3][4],第2行第3列元素的正 确表示方法为。 (1) &a[2][3] (2)a[2]+3 (3) *(a+2)+3 (4)*(a[2]+3) 10.5 指向一个包含4个整型元素的一维数组的指针 变量的定义形式为: (1) int (*p)[4] (2) int *p[4] (3) int * (p[4]) (4) int (*p)[ ] 第10 章 课堂练习

  41. 10.6 若有语句:int a=4,*p=&a; 下面均代表地址的一组选项的是: 1) a,p,&*a 2) *&a,&a,*p 3) &a,p,&*p 4) *&p,*p,&a 10.7 以下程序段的输出结果为: char a[]=“Program”,*ptr; ptr =a; for ( ;ptr<a+7;ptr+=2) putchar(*ptr); 1) Program 2) Porm 3) 有语法错误; 4) Por 第10 章 课堂练习

More Related