1 / 43

第 10 章 指 针

第 10 章 指 针. 指针是C语言中的重要概念,也是C语言的重要特色。使用指针,可以使程序更加简洁、紧凑、高效。. §10.1 指针的概念. 一 . 内存单元的内容、内存单元地址 : 内存区域划分为一个一个的内存单元,一个内存单元 可以存放一字节数据,每一个内存单元都有一个地址。 例: int i=3 ; char j=‘s’;. 地址. 内存单元. 3. 2002 2004 3000. 2000 2001. 变量 i 变量 j. 编译时为变量 i 分配 2000 和 2001 两

julio
Download Presentation

第 10 章 指 针

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. 第10章 指 针 指针是C语言中的重要概念,也是C语言的重要特色。使用指针,可以使程序更加简洁、紧凑、高效。

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

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

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

  5. §10.2 变量的指针 一、指针变量的定义 类型标识符* 标识符 例如:int *cm • “标识符”是指针变量名 • “*”表示定义指针变量 • “类型标识符”表示该指针变量所指向的变量类型。 • 指针是一个变量的地址,为了表示指针与它指向变量的地址之间的关系,用*表示指向.

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

  7. 三、指针变量的赋值: /*整型变量a的地址赋给指针变量pa*/ /*指针变量p取得整型变量a的地址.*/ /*指针pa的值赋给指针pb*/ /*将数组的首地址赋给相同类型的指针*/ /*将字符串的首地址赋给指针变量*/ (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”;

  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. p1 a [例10.2]输入a和b两个整数,按先大后小的顺序输出a和b。 See:9_2.c 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 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。 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 a[0] pa &a[0] 2 3 4 5 6 a[6] 7 §10.3 数组的指针 • 指针可以指向数组和数组元素,对数组元素的访问: 既可以使用数组下标,也可以使用指针. 一、指向数组元素的指针变量 指向数组元素的指针变量,其类型应与数组元素相同. 例1: int a[7]; int *pa; pa=&a[0]; 或 pa=a; 例2: float b[10],*pb=b ; 或 float b[10],pb=&b[0];

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

  13. [例10.5]输出数组的全部元素。(设10个元素,整型)。[例10.5]输出数组的全部元素。(设10个元素,整型)。 • 访问各元素有三种方法: 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] ); }

  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 () (see:9_5.c) { 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. 三、数组名作函数参数1、形参和实参都用数组名三、数组名作函数参数1、形参和实参都用数组名 f( int arr[ ],int n) { … } 例:main() {int array[10]; … f(array,10); … }

  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编译系统将形参数组名作为指针变量处理.实际上,c编译系统将形参数组名作为指针变量处理. 若有定义 :f(int arr[ ],int n) 编译后:f(int *arr,int n)

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

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

  24. 数组a a 数组b I b a m a b o y . \0 用数组名计算数组元素的地址 [例10.18]将字符串a复制到字符串b。 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"); } 特点:不移动指针

  25. p1 数组a p2 数组b I a m a b o y . \0 特点:移动执针 [例10.19]:用指针处理字串复制. 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"); } I a m a b o y . \0

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

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

  28. [例9.23]求a和b中的大者。 用函数名调用函数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); • }

  29. 用函数指针调用函数max() • int max(int x, int y) /*原型*/ • {int z; • if (x>y) z = x; • else z = y; • return z;} • main () • { int (*p) ( );/*定义函数指针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);} 用函数指针变量调用函数时,只须将(*p)代替函数名max,并加上实参

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

  31. §10.7 指针数组和指向指针的指针(自学) 一、指针数组 概念:指针数组是一个数组,该数组中的 每一个元素是指针变量。 形式:类型标识符 *数组名[数组元素个数] 例: int * p[4]; 定义一个指针数组,数组名p,有4个元素, 每一个元素是指向整型变量的指针。

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

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

  34. §10.8 指针使用小结 一、有关指针的数据类型 定义: • 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是指针,指向一个指向整型数据的指针

  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不是指向同一个数组的元素,比较无意义。

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

  39. 第10 章 习 题 10.1 指针变量a所指的字符串长度为, 这个长度是可以用strlen(a)测出来的。 char *a=“\nMY Name is\”zhang li\”.\n”; (1)28 (2) 27 (3) 26 (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); } *p1,*p2

  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 下列程序的输出结果是 A)44 B)22 C)24 D)结果错误 main() {int a[5]={2,4,6,8,10},*p,**k; p=a;k=&p; printf("%d",*(p)); printf("%d\n",**k); }

  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

  42. 10.8下面说明不正确的是: 1) int *a[4]; 2) float (*p)(); 2) int **p; 4) char *(*a)[];

  43. 作业 10.1 10.2 10.6 10.11 • 上机实验 学生成绩管理(使用指针): 1.学生姓名与成绩录入; 2.求学生平均成绩并输出; 3.将不及格的学生姓名与成绩输出; 4.按从高到低成绩排序并输出.

More Related