第
This presentation is the property of its rightful owner.
Sponsored Links
1 / 43

第 10 章 指 针 PowerPoint PPT Presentation


  • 122 Views
  • Uploaded on
  • Presentation posted in: General

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

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


10

第10章 指 针

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


10

§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


10

二.内存单元的访问:

j

  • 直接访问:通过变量名访问。

    char j=‘s’;

    printf(“%c”, j );

  • 间接访问:通过该变量的指针来访问。

    p=&j;

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

75

2000

p

j

75

2000


10

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

    是常量。

  • 指针变量:是指取值为地址的变量,其

    值是另一个变量的地址。

  • 要引用指针,必须定义指针。

  • 定义指针,是为了通过指针访问内存单元。

  • 一个数组或函数占有一段连续内存单元,假如将一个数组或函数的首地址赋给指针变量,通过指针就可以找到数组或函数。


10

§10.2 变量的指针

一、指针变量的定义

类型标识符* 标识符

例如:int *cm

  • “标识符”是指针变量名

  • “*”表示定义指针变量

  • “类型标识符”表示该指针变量所指向的变量类型。

  • 指针是一个变量的地址,为了表示指针与它指向变量的地址之间的关系,用*表示指向.


10

a

2000

5

b

2002

...

...

p

3000

&a

2000

二、指针变量的引用

  • 未经赋值的指针变量不能用。

  • 指针变量只能赋予地址。

    C语言提供两种相关地址运算符:

    &: 取地址运算符

    *: 取内容运算符

    * \ &优先级相同.

    例:int a=5,b;

    int *p;

    p=&a;

    b=*p;

类型说明中的*表示

定义指针变量

p

a

表达式中的*是运算符

&a

5


10

三、指针变量的赋值:

/*整型变量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”;


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

  • }

  • 程序运行结果:

pointer-1

a

100

&a

100,10

100,10

b

pointer-2

10

&b


10

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


10

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


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)等效.


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

    }


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

}

特点:不移动指针


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

    }

特点:移动执针


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个元素吗?


10

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

f( int arr[ ],int n)

{

}

例:main()

{int array[10];

f(array,10);

}


10

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

例:main()

{int array[10];

f(array,10);

}

f( int *arr,int n)

{

}


10

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

例:main()

{int array[10],*p;

p=array;

f(p,10);

}

f( int *arr,int n)

{

}


10

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

例:main()

{int array[10],*p;

p=array;

f(p,10);

}

f( int arr[ ],int n)

{

}


10

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

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

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


10

§10.4 字符串的指针

一、字符串的表现形式

C语言中,有两种方式可以实现字符串:

字符数组、字符指针。

[例10.16]:字符数组

main()

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

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

}

用字符串对字符数组赋值

string是数组名,代表字符数组的首地址。

数组可以用下标访问,也可以用指针访问


10

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.


10

数组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");

}

特点:不移动指针


10

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


10

  • 例10.21:

  • main()

  • { char *a=“I love china!”;

  • a=a+7;

  • printf(“%s”,a);

  • }

  • 运行结果如下:

  • China!

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


10

§10.5 函数指针

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

  • 函数指针定义的一般形式:

    函数返回值类型(*指针变量名)( )

    例: int (*p) ( )

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

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


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

  • }


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,并加上实参


10

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

一般形式:

类型标识符 * 函数名(参数表)

例、int * a (int x, int y)

  • 声明一个函数,函数名为a,其返回值类型是“指向整型的指针”,

  • 函数形式参数为int x 和 int y。

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


10

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

一、指针数组

概念:指针数组是一个数组,该数组中的

每一个元素是指针变量。

形式:类型标识符 *数组名[数组元素个数]

例: int * p[4];

定义一个指针数组,数组名p,有4个元素, 每一个元素是指向整型变量的指针。


10

p

name[0]

name[1]

name[2]

Ann

Hare

Jack

二、指向指针的指针

定义举例:

char * * p;

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

p=name;

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

name指针数组

二维字符数组


10

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


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


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


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。


10

4、指针变量相减。

  • 当p1、p2指向同一个数组的元素,指针相减p2-p1等于p1、p2间的元素个数。

  • 注意:指针相加无意义。

    5、两个指针的比较

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


10

三、空类型指针 void *

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

  • 空类型指针与其他类型指针之间赋值时,应进行强制类型转换.

    例、 char *p1;

    void *p2;

    p1 = (char *)p2;

    p2 = (void *)p1;


10

第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


10

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

}


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


10

10.8下面说明不正确的是:

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

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


10

  • 作业

    10.1 10.2 10.6 10.11

  • 上机实验

    学生成绩管理(使用指针):

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

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

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

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


  • Login