第 十 章 指 针

41
第 第 第 第 第 第

Upload: macha

Post on 12-Jan-2016

160 views

Category:

Documents


2 download

DESCRIPTION

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

TRANSCRIPT

Page 1: 第 十 章  指    针

第 十 章 第 十 章

指 针指 针

Page 2: 第 十 章  指    针

§10.1 §10.1 指针的概念指针的概念一、内存单元的内容和内存单元的地址: 内存区域被划分成一个一个的内存单元,一个内存单元可以存放一个字节的数据,每一个内存单元都有一个编号,统称为地址。 例: int i=3 ; char j=‘s’;

变量 i

变量 j

编译时为变量 i 分配 2000 和 2001 两个字节的内存单元 , 为 j 分配 2003一个字节的内存单元2002

2004

3000

20002001

2003

地址

7575

内存单元

因为内存单元的地址就是“指向”了该内存单元,故通常把内存单元的地址称为指针。

33

Page 3: 第 十 章  指    针

二二 .. 内存单元的访问:内存单元的访问:直接访问:通过变量名访问。

char j=‘s’; printf(“%c”, j );

间接访问:通过该变量的指针来访问。 p=&j;

称:指针变量 p 指向变量 j , p 是变量 j 的指针。

752000

j

752000

jp

Page 4: 第 十 章  指    针

变量的指针:是一个变量的地址 , 是常量。指针变量:是存放变量地址的变量,其

值是该变量的地址。

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

Page 5: 第 十 章  指    针

§10.2 §10.2 变量的指针变量的指针

一、指针变量的定义 类型标识符 * 标识符

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

Page 6: 第 十 章  指    针

二、指针变量的引用指针变量只能存放地址。未经赋值的指针变量不能用。

C 语言提供两种相关地址运算符: &: 取地址运算符 *: 取内容运算符 * 和 & 的优先级相同。例 : int a=5,b; int *p; p=&a; b=*p;

类型说明中的 * 表示定义指针变量

表达式中的 * 是运算符*p 表示 p 指向地址里的值

52000

2002

a , b

......

3000

p

2000 &a

&a 5

p a

Page 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*/

/* 将字符串的首地址赋给指针变量 */

Page 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 ); } 程序运行结果: &a

&b

100

10

pointer-1

pointer-2

a

b

100 , 10 100 , 10

Page 9: 第 十 章  指    针

[ 例 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

&a 5

p1 a

&b 9

p2 b

p

a=5,b=9; max=9,min=5该例不交换变量 a 、 b 的值,而是交换指针 p1 、 p2 的值。

&b

&a

Page 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 的地址传送给形参

Page 11: 第 十 章  指    针

§10.3 §10.3 数组的指针数组的指针

指针可以指向数组和数组元素 , 对数组元素的访问 : 既可以使用数组下标 , 也可以使用指针。一、指向数组元素的指针变量一、指向数组元素的指针变量 指向数组元素的指针变量,其类型应与数组元素相 同。例 1: int a[7]; int *p; p=&a[0]; 或 p=a;

例 2: float b[10],*p=b ; 或 float b[10],p=&b[0];

1

2

3

4

5

6

7

&a[0]p a[0]

a[6]

/* 指的是把数组 a 的首地址赋给指针 p*/

Page 12: 第 十 章  指    针

二、通过指针引用数组元素二、通过指针引用数组元素

设设 :int a[10],*p=&a[0];:int a[10],*p=&a[0];(1).p+1(1).p+1 和和 a+1a+1 都是指向下一个元素都是指向下一个元素 a[1]; a[1];

如果数组元素是整型, p+1 表示 p 的地址加 2 ;如果数组元素是实型, p+1 表示 p 的地址加 4 ;

a 表示数组首地址。

p+i p+i 和和 a+i a+i 指向元素指向元素 a[i]a[i] 。。(2).*(p+i) (2).*(p+i) 访问元素访问元素 a[i];a[i]; 例例 : *(p+5): *(p+5) 和和 *(a+5) *(a+5) 与与 a[5]a[5] 等效等效 ;;(3).(3). 指向数组指针可以带下标指向数组指针可以带下标 :: 例例 : p[i]: p[i] 与与 *(p+i)*(p+i) 等效等效 ..

Page 13: 第 十 章  指    针

11 、下标法、下标法 main () main () { { int a[10]; int a[10]; int i; int i; for(i=0;i<10;i++) for(i=0;i<10;i++) scanf("%d", &a[i]); scanf("%d", &a[i]); printf("\n"); printf("\n"); for(i=0;i<10;i++) for(i=0;i<10;i++) printf("%d ", a[i] ); printf("%d ", a[i] ); } }

[ 例 10.5] 输出数组的全部元素。(设 10 个整数)

特点特点 :: 常用、过程简单直观常用、过程简单直观

Page 14: 第 十 章  指    针

22 、用数组名计算数组元素的地址。、用数组名计算数组元素的地址。

main( ) main( ) { { int a[10]; int a[10]; int i; int i; for(i=0;i<10;i++) for(i=0;i<10;i++) scanf("%d", &a[i]); scanf("%d", &a[i]); printf("\n"); printf("\n"); for(i=0;i<10;i++) for(i=0;i<10;i++) printf("%d ", *(a+i) ); printf("%d ", *(a+i) ); } }

特点特点 :: 不移动指针不移动指针但要计算每个元素的地址但要计算每个元素的地址费时间费时间

Page 15: 第 十 章  指    针

33 、用指针访问各元素。、用指针访问各元素。

main () main () { { int a[10]; int a[10]; int *p , i; int *p , i; for(i=0;i<10;i++) for(i=0;i<10;i++) scanf("%d", &a[i]); scanf("%d", &a[i]); printf("\n"); printf("\n"); for( p=a ; p<(a+10) ; p++ ) for( p=a ; p<(a+10) ; p++ ) /* p++/* p++ 使使 pp 指向下一个元素 指向下一个元素 */*/ printf("%d ", *p ); printf("%d ", *p ); } }

特点特点 :: 移动指针移动指针速度快速度快

Page 16: 第 十 章  指    针

例:通过以下程序输出例:通过以下程序输出 aa 数组中的数组中的 1010 个元素。 个元素。

main()main(){{

int a[10],*p,i;int a[10],*p,i;p=a;p=a;for(i=0;i<10;i++)for(i=0;i<10;i++)

scanf("%d",scanf("%d",p++p++););printf("\n");printf("\n");for(i=0;i<10;i++,for(i=0;i<10;i++,p++p++))

printf("%d\t",*p);printf("%d\t",*p);}}

????试问:以上程序可以输出试问:以上程序可以输出 aa 数组中数组中的的 1010 个元素吗?个元素吗?

Page 17: 第 十 章  指    针

11 、形参和实参都用数组名、形参和实参都用数组名

main()main() {{ int array[10];int array[10]; … … ff( array ,10);( array ,10); … … }}

ff( int arr[],int n)( int arr[],int n){{ ……

}}

三、数组名作函数参数三、数组名作函数参数

Page 18: 第 十 章  指    针

main()main() {{ int array[10];int array[10]; … … ff(array(array ,10);,10); … … }}

ff( int *arr,int n)( int *arr,int n){{……

}}

22 、实参用数组名,形参用指针变量。、实参用数组名,形参用指针变量。

Page 19: 第 十 章  指    针

main()main(){{ int array[10]int array[10] ,, *p;*p; p=array;p=array; … … ff(p,10);(p,10); … …}}

ff( int *arr,int n)( int *arr,int n){{ … …

}}

33 、实参、形参都用指针变量。、实参、形参都用指针变量。

Page 20: 第 十 章  指    针

main()main(){{ int array[10]int array[10] ,, *p;*p; p=array;p=array; … … ff(p,10);(p,10); … …}}

ff( int arr[ ],int n)( int arr[ ],int n){{……

}}

44 、实参用指针变量,形参用数组名。、实参用指针变量,形参用数组名。

Page 21: 第 十 章  指    针

§10.4 §10.4 字符串的指针字符串的指针

一、字符串的表现形式一、字符串的表现形式 CC 语言中,有两种方式可以实现字符串:语言中,有两种方式可以实现字符串: 字符数组、字符指针。字符数组、字符指针。

[[ 例例 10.16]10.16] :字符数组:字符数组 main() main() { char string[ ] ={“How are you!”}; { char string[ ] ={“How are you!”}; printf("%s\n",string); printf("%s\n",string); } }

string 是数组名,代表字符数组的首地址。数组可以用下标访问,也可以用指针访问

用字符串对字符数组赋值

Page 22: 第 十 章  指    针

main() main()

{ {

char *name1 =”Mary";char *name1 =”Mary";

char *name2=“Hare”;char *name2=“Hare”;

   printf("%10s%10s\n",name1,name2); printf("%10s%10s\n",name1,name2);

} }

name1 、 name2 是指针变量

char *name1 =“Mary”; 等价于 : char * name1; name1 = “Mary”;它把字符串常量的首地址赋给指针 name1.

name1

name2

Mary

Hare

[[ 例例 10.17]10.17] 字符指针字符指针

Page 23: 第 十 章  指    针

main () main () { char a[ ] = "I am a boy."; { char a[ ] = "I am a boy."; char b[20]; char b[20]; int i; int i; for (i=0; *(a+i) !='\0'; i++) for (i=0; *(a+i) !='\0'; i++) *(b+i) = *(a+i); *(b+i) = *(a+i); *(b+i) = '\0'; *(b+i) = '\0'; printf("string a is: %s\n",a); printf("string a is: %s\n",a); printf("string b is:"); printf("string b is:"); for (i=0; b[i] !='\0'; i++) for (i=0; b[i] !='\0'; i++) printf("%c",b[i]); printf("%c",b[i]); printf("\n"); printf("\n"); } }

I

am

数组 a

a

a

boy.\0

数组 b

bb

特点 :不移动指针

用数组名计算数组元素的地址

[[ 例例 10.18] 10.18] 将字符串将字符串 aa复制到字符串复制到字符串 bb 。。

Page 24: 第 十 章  指    针

main ()main () { char a[ ] = "I am a boy.",b[20],*p1,*{ char a[ ] = "I am a boy.",b[20],*p1,*

p2;p2; int i;int i; p1=a;p2=b;p1=a;p2=b; for ( ; *p1 !='\0'; p1++,p2++)for ( ; *p1 !='\0'; p1++,p2++) *p2 = *p1; *p2 = *p1; *p2 = '\0';*p2 = '\0'; printf("string a is: %s\n",a);printf("string a is: %s\n",a); printf("string b is:");printf("string b is:"); for (i=0; b[i] !='\0'; i++)for (i=0; b[i] !='\0'; i++) printf("%c",b[i]);printf("%c",b[i]); printf("\n");printf("\n"); }}

I

am

数组 ap1p1

a

boy.\0

数组 bp2

特点 :移动指针

[[ 例例 10.19]:10.19]: 用指针处理字串复制用指针处理字串复制 ..

Page 25: 第 十 章  指    针

例 10.21:main(){ char *a=“I love china!”; a=a+7; printf(“%s”,a);}运行结果如下 : China!

(a+7) 是用指针指向数组元素 a[i] 的第 7 个字符

Page 26: 第 十 章  指    针

可以看到:可以看到:

1 、字符数组和字符指针的概念不同。

2 、字符指针指向字符串,而 C 语言中,字符串按数组方式处理,因此,字符指针和字符数组的访问方式相同。

Page 27: 第 十 章  指    针

§10.5 §10.5 函数指针函数指针

一、用函数指针变量调用函数一、用函数指针变量调用函数

函数指针定义的函数指针定义的一般形式一般形式:: 函数返回值类型(函数返回值类型( ** 指针变量名)( )指针变量名)( )

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

Page 28: 第 十 章  指    针

用用函数名函数名调用子函数调用子函数 max()max()

int int maxmax(int x, int y); /*(int x, int y); /*原型原型 */ */ {int z; {int z; if (x>y) z = x; if (x>y) z = x; else z = y; else z = y; return z; return z; } }

main () main () {int a,b,c; {int a,b,c; scanf("%d,%d", &a, &b); scanf("%d,%d", &a, &b); c = c = maxmax(a, b); (a, b); printf("a=%d,b=%d,max=%d",a,b,c); printf("a=%d,b=%d,max=%d",a,b,c); } }

[[ 例例 9.23] 9.23] 求求 aa 和和 bb 中的大者。中的大者。

Page 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);}

用函数指针变量调用函数时,只须将 (*p)代替函数名 max ,并

加上实参

[[ 例例 9.23] 9.23] 求求 aa 和和 bb 中的大者。中的大者。

Page 30: 第 十 章  指    针

§10.6 §10.6 返回指针的函数返回指针的函数((自学自学 ))

一般形式:  类型标识符 * 函数名(参数表)

例、   int * a (int x, int y)声明一个函数,函数名为 a ,其返回值类型是“指向整型的指针”,函数形式参数为 int x 和 int y 。

注意 :在 a 的两侧分别为 * 运算符和 ( ) 运算符 ,a 先与 ( )结合 ,这是函数形式 ; 函数前有个 * 号 , 表示该函数为指针型函数 .

Page 31: 第 十 章  指    针

§10.7 §10.7 指针数组和指向指针的指针指针数组和指向指针的指针((自学自学 ))

一、指针数组一、指针数组概念:指针数组是一个数组,该数组中的 每一个元素均是指针变量。形式:类型标识符 * 数组名[数组元素个数]

例: int * p[4];  定义一个指针数组,数组名 p ,有 4 个元素, 每一个元素是指向整型变量的指针。如:

char *name[3]={”math”,”computer”,”ccm”};可用 puts(name[i]) 语句输出。

Page 32: 第 十 章  指    针

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

name[0]

name[1]

name[2]

Ann

Hare

Jack

p

二维字符数组name 指针数组

Page 33: 第 十 章  指    针

main() main() {{ int i;int i; char *name[]={"Ann","Hare","Jack","Mary"}; char *name[]={"Ann","Hare","Jack","Mary"}; char **p;char **p; printf("\n Students's names are:\n");printf("\n Students's names are:\n"); for(i=0;i<4;i++)for(i=0;i<4;i++) { p=name+i; { p=name+i; printf("%6s\t",*p); printf("%6s\t",*p); }} }}

运行结果运行结果 : : Ann Hare Jack MaryAnn Hare Jack Mary

name[0]

name[1]

name[2]

Ann

Hare

Jack

p

二维字符数组name 指针数组

name[3] mary

程序举例:程序举例:

Page 34: 第 十 章  指    针

§10.8 §10.8 指针使用小结指针使用小结

一、有关指针的数据类型一、有关指针的数据类型定义定义 : : int i; int i; 定义整型变量定义整型变量 i i int *p; int *p; pp 是指向整型数据的指针变量是指向整型数据的指针变量 int a[n]; int a[n]; 定义数组定义数组 aa ,元素类型为,元素类型为 intint ,元素个数是,元素个数是 nn int *p[n]; int *p[n]; pp 是指针数组是指针数组 ,,包含包含 nn 个指针个指针 ,, 每一个指针可每一个指针可 以指向整型数据 以指向整型数据 int f(); int f(); ff 是函数,返回值是是函数,返回值是 int int int (*p)(); int (*p)(); pp 是函数指针,所指向的函数返回整型数据是函数指针,所指向的函数返回整型数据 int *p(); int *p(); pp 是函数,返回值是指针,该指针指向整型数据 是函数,返回值是指针,该指针指向整型数据 int **p; int **p; pp 是指针,指向一个指向整型数据的指针是指针,指向一个指向整型数据的指针

Page 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

Page 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 。

Page 37: 第 十 章  指    针

4、指针变量相减当 p1 、 p2 指向同一个数组的元素,指针相减 p2-p1 等于 p

1 、 p2 间的元素个数。注意:指针相加无意义。

5 、两个指针的比较当 p1 、 p2 指向同一个数组的元素时可以比较,如 :p1 > p2 。

表示 p1在 p2之后。若 p1 、 p2 不是指向 同一个数组的元素,比较无意义。

Page 38: 第 十 章  指    针

三、空类型指针 void void *p ,表示 p 是空类型指针,它可以指向任何数据

类型。空类型指针与其他类型指针之间赋值时,应进行强制类

型转换,例、   char *p1;     void *p2;     p1 = (char *)p2;     p2 = (void *)p1;

Page 39: 第 十 章  指    针

第第 10 10 章 课堂练习章 课堂练习10.1 10.1 指针变量指针变量 aa 所指的字符串长度为所指的字符串长度为 ,, 这个长度是可以用这个长度是可以用 strlen(a)strlen(a)测出来的。测出来的。 char *a=“\nMY Name is\”zhang li\”.\n”;char *a=“\nMY Name is\”zhang li\”.\n”; (1)26 (2) 27 (3) 28 (4) 24 (5) 23(1)26 (2) 27 (3) 28 (4) 24 (5) 23

10.2 10.2 下面程序的作用是下面程序的作用是 : : 将两个变量中的值互换,将两个变量中的值互换, 请检查程序是否正确,如不正确的,改正之。请检查程序是否正确,如不正确的,改正之。 main ( )main ( ) {{ int a=3,b=4;int a=3,b=4; int *p1,*p2,*p;int *p1,*p2,*p; p1=&ap1=&a ;; p2=&b;p2=&b; p=p1;p1=p2;p2=p;p=p1;p1=p2;p2=p; printf(“a= %d,b= %d\n”,a,b);printf(“a= %d,b= %d\n”,a,b); }}

Page 40: 第 十 章  指    针

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

第第 10 10 章 课堂练习章 课堂练习

Page 41: 第 十 章  指    针

10.6 10.6 若有语句若有语句 :int a=4,*p=&a;:int a=4,*p=&a; 下面均代表地址的一组选项的是下面均代表地址的一组选项的是 :: 1) a,p,&*a 2) *&a,&a,*p1) a,p,&*a 2) *&a,&a,*p 3) &a,p,&*p 4) *&p,*p,&a3) &a,p,&*p 4) *&p,*p,&a

10.7 10.7 以下程序段的输出结果为以下程序段的输出结果为 :: char a[]=“Program”,*ptr;char a[]=“Program”,*ptr; ptr =a;ptr =a; for ( ;ptr<a+7;ptr+=2) for ( ;ptr<a+7;ptr+=2) putchar(*ptr);putchar(*ptr); 1) Program 2) Porm1) Program 2) Porm 3) 3) 有语法错误有语法错误 ; 4) Por; 4) Por

第第 10 10 章 课堂练习章 课堂练习