第 10 章 指 针

43
第 10 第 第 第 指指指 指指指指指 指指指 指指指指指 指指指 指指指 指指指指指指指指 指 ,C。 指指指 指指指 指指指指指指指指 指 ,C。 指指指 指指指指指指指指指指 指指指 ,、、 指指指 指指指指指指指指指指 指指指 ,、、 指指指指

Upload: julio

Post on 12-Jan-2016

104 views

Category:

Documents


6 download

DESCRIPTION

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

TRANSCRIPT

Page 1: 第 10 章  指 针

第 10 章 指 针 指针是C语言中的重指针是C语言中的重要概念,也是C语言的重要概念,也是C语言的重要特色。使用指针,可以要特色。使用指针,可以使程序更加简洁、紧凑、使程序更加简洁、紧凑、高效。高效。

Page 2: 第 10 章  指 针

§10.1 指针的概念 一 . 内存单元的内容、内存单元地址: 内存区域划分为一个一个的内存单元,一个内存单元 可以存放一字节数据,每一个内存单元都有一个地址。 例: int i=3 ;

char j=‘s’; 变量 i

变量 j

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

2002

2004

3000

20002001

2003

地址

75

2003

内存单元

通常把内存单元的地址称为指针 .

指针变量 j-pointer

3

Page 3: 第 10 章  指 针

二 .内存单元的访问: 直接访问:通过变量名访问。 char j=‘s’;

printf(“%c”, j );

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

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

752000j

752000

jp

Page 4: 第 10 章  指 针

指针( pointer ):是一个变量的地址 ,

是常量。

指针变量:是指取值为地址的变量,其 值是另一个变量的地址。

要引用指针 , 必须定义指针。 定义指针 , 是为了通过指针访问内存单元。 一个数组或函数占有一段连续内存单元 , 假如将

一个数组或函数的首地址赋给指针变量 , 通过指针就可以找到数组或函数。

Page 5: 第 10 章  指 针

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

例如: int *cm “ 标识符”是指针变量名 “*” 表示定义指针变量 “ 类型标识符”表示该指针变量所指向的变量

类型。 指针是一个变量的地址 , 为了表示指针与它指

向变量的地址之间的关系 , 用 * 表示指向 .

Page 6: 第 10 章  指 针

二、指针变量的引用 未经赋值的指针变量不能用。 指针变量只能赋予地址。 C 语言提供两种相关地址运算符: &: 取地址运算符 *: 取内容运算符 * \ & 优先级相同 .

例 : int a=5,b; int *p; p=&a; b=*p;

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

表达式中的 * 是运算符

52000 a

2002 b

......

3000 p

2000 &a

&a 5

p a

Page 7: 第 10 章  指 针

三、指针变量的赋值 :(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*/

/* 将数组的首地址赋给相同类型的指针 */

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

Page 8: 第 10 章  指 针

[ 例 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 章  指 针

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

&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 章  指 针

四、指针变量作为函数的参数[ 例 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 章  指 针

§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];

1

2

3

4

5

6

7

&a[0]pa a[0]

a[6]

Page 12: 第 10 章  指 针

二、通过指针引用数组元素 设 :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) 等效 .

Page 13: 第 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] ); }

Page 14: 第 10 章  指 针

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

}

特点 : 不移动指针

Page 15: 第 10 章  指 针

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

}

特点 : 移动执针

Page 16: 第 10 章  指 针

例:通过以下程序输出 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 个元素吗?

Page 17: 第 10 章  指 针

三、数组名作函数参数1 、形参和实参都用数组名

例 :main()

{int array[10];

f(array,10);

}

f( int arr[ ],int n)

{

}

Page 18: 第 10 章  指 针

例 :main()

{int array[10];

f(array,10);

}

f( int *arr,int n)

{

}

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

Page 19: 第 10 章  指 针

例 :main()

{int array[10] , *p;

p=array;

f(p,10);

}

f( int *arr,int n)

{

}

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

Page 20: 第 10 章  指 针

例 :main()

{int array[10] , *p;

p=array;

f(p,10);

}

f( int arr[ ],int n)

{

}

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

Page 21: 第 10 章  指 针

实际上 ,c 编译系统将形参数组名作为指针变量处理 .

若有定义 :f(int arr[ ],int n)

编译后 :f(int *arr,int n)

Page 22: 第 10 章  指 针

§10.4 字符串的指针一、字符串的表现形式 C 语言中,有两种方式可以实现字符串: 字符数组、字符指针。 [ 例 10.16] :字符数组 main()

{ char string[ ] ={"I love China!”};

printf("%s\n",string);

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

用字符串对字符数组赋值

Page 23: 第 10 章  指 针

[ 例 10.17] 字符指针 main()

{ char *name1 =”Mary";

char *name2=“Hare”;

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

}

name1 是一个指针变量

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

name1

name2

Mary

Hare

Page 24: 第 10 章  指 针

[ 例 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"); }

I

am

数组 a

a

a

boy.

\0

数组 b b

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

特点 : 不移动指针

Page 25: 第 10 章  指 针

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

am

数组 ap1

a

boy.

\0

数组b

p2

特点 : 移动执针

I

am

a

boy.\0

Page 26: 第 10 章  指 针

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

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

Page 27: 第 10 章  指 针

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

例 : int (*p) ( )

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

C 规定 : 函数的名称就是函数的入口地址

Page 28: 第 10 章  指 针

[ 例 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); }

Page 29: 第 10 章  指 针

用函数指针调用函数 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 ,并加上实参

Page 30: 第 10 章  指 针

§10.6 返回指针的函数 ( 自学 )一般形式:  类型标识符 * 函数名(参数表)例、   int * a (int x, int y) 声明一个函数,函数名为 a ,其返回值类型是

“指向整型的指针”, 函数形式参数为 int x 和 int y 。

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

Page 31: 第 10 章  指 针

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

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

例: int * p[4];  定义一个指针数组,数组名 p ,有 4 个元素, 每一个元素

是指向整型变量的指针。

Page 32: 第 10 章  指 针

二、指向指针的指针 定义举例:  char * * p;

char *name[]={“Ann”,“Hare”,“Jack”};

p=name;

p 是一个指向指针的指针 . 被 p 指向的指针指向字符变量。

name[0]

name[1]

name[2]

Ann

Hare

Jack

p

二维字符数组name 指针数组

Page 33: 第 10 章  指 针

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[0]

name[1]

name[2]

Ann

Hare

Jack

p

二维字符数组name 指针数组

name[3] mary

Page 34: 第 10 章  指 针

§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 是指针,指向一个指向整型数据的指针

Page 35: 第 10 章  指 针

二、指针运算小结

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: 第 10 章  指 针

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: 第 10 章  指 针

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

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

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

如、 p1 > p2 。若 p1 、 p2 不是指向同一个数组的元素,比较无意义。

Page 38: 第 10 章  指 针

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

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

类型转换 .

例、   char *p1;     void *p2;     p1 = (char *)p2;     p2 = (void *)p1;

Page 39: 第 10 章  指 针

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

Page 40: 第 10 章  指 针

10.3 已设 p1 和 p2 为指针变量,且已指向同一个整 型数组中的元素, a 是一个整型变量,问下面 哪一个语句不能正确执行 ? (1) a=*p1 (2) a=*p1+*p2 (3) a=*p1-*p2 (4) p1=a-p210.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);

}

Page 41: 第 10 章  指 针

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

Page 42: 第 10 章  指 针

10.8 下面说明不正确的是 :

1) int *a[4]; 2) float (*p)();

2) int **p; 4) char *(*a)[];

Page 43: 第 10 章  指 针

作业 10.1 10.2 10.6 10.11

上机实验 学生成绩管理 ( 使用指针 ):

1. 学生姓名与成绩录入 ;

2. 求学生平均成绩并输出 ;

3. 将不及格的学生姓名与成绩输出 ;

4. 按从高到低成绩排序并输出 .