第 8 章 指针 指针 : c 的一个 重要概念 、 重要特色 。它使 c...

59
第8第 第第 第第 :C第 第第第第第第第第 第第 C 第第第第第第第第第 C 第第第第第第第第第第 第第第第第第第第第第 第第第第第第第第第 。, 第第第第第第第第第第第第第第第第第第第第第第第第第第 C 第第第第第

Upload: cale

Post on 12-Jan-2016

122 views

Category:

Documents


10 download

DESCRIPTION

第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。 不掌握 指针 等于没有掌握 C 语言的 精华 。. 8 . 1 指针的概念 简单地说, 指针就是地址 。 要掌握指针的概念就必须弄清: ■ 内 s 存地址概念 ? ■ 变量与地址的关系 ? ■ 如何通过地址进行变量的存取 ?. int i,j,k; i=3; j=6; k=i+j;. 程序经编译后,变量名被转化为对应的存储单元的地址。. 说明例: - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

第 8 章 指针 指针 :C 的一个重要概念、重要特色。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

不掌握指针等于没有掌握 C 语言的精华。

Page 2: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

8 . 1 指针的概念

简单地说,指针就是地址。

要掌握指针的概念就必须弄清:

■ 内 s 存地址概念 ?

■变量与地址的关系 ?

■如何通过地址进行变量的存取 ?

Page 3: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

说明例:

内存用户数据

1000 3 i

1002 6 j

1004 9 k

对变量值的存取总是按地址进行的 ----直接访问。

int i,j,k;i=3; j=6;k=i+j;

程序经编译后,变量名被转化为对应的存储单元的地址。

Page 4: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

也可以采用“间接访问”方式: 先将变量 i 的地址存放到另一变量 p1中,要访问 i 时,先取出 p1的内容(变量 i的地址),再去访问该地址所对应的内存单元中的内容(变量 i 的值)。

Page 5: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

内存用户数据

1000 3 i

1002 6 j

1004 9 k

2000 1000 p1

2004 1002 p2

int i,j,k;i=3; j=6;k=i+j;int *p1, *p2;p1=&i;p2=&j;

Page 6: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

在以上概念的基础上对指针下定义:

变量的地址就是该变量的指针。存放地址的变量称指针变量。p1是指向变量 i 的指针变量。

1000

1002

1004

1000

1002

i

j

k

p1p2

Page 7: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

8 . 2 变量的指针和指向变量的指针变量 变量的指针 指针变量 指向变量的指针变量 用“ *” 代表“指向” 如 *p1 代表它所指向的变量 i ,同一内存单元。 以下两个语句等价: i=3; 直接访问 *p1=3; 间接访问

Page 8: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

内存用户数据

1000 3 i

1002 6 j

1004 9 k

2002 1000 p1

2004 1002 p2

int i,j,k;i=3; j=6;k=i+j;int *p1=&i;int *p2=&j;

*p1=4;

4

Page 9: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■指针变量的定义 指针变量也必须先定义后使用。 int *p1; ① * 表示该变量为指针变量,但变量名是 p1。 ② 一个指针变量只能指向同一类型的变量。 ③ 初始化 . ④ 所占用的内存空间,操作系统 32位、 64位 int i,*p1; int i; float a; int *p1=&i; p1=&i; 合法 p1=&a; 不合法

Page 10: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■指针变量的使用 两种用法: ①用地址运算符 & p1=&i; ②用指针运算符 * (实行间接访问) *p1=100; k=*p1;注意: 1 指针变量只能放地址(指针) 2 必须初始化才能使用。 3 不能把地址赋给 *p

int i; int *p1,*p2; p1=100; p1=&i; *p1=100; *p2=100; p2=p1; *p2=10; *p1=&i;

Page 11: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:main()

{ int a=100,b=10;

int *p1,*p2; 定义指针变量,尚无体指向 p1=&a; p1指向 a p2=&b; p2指向 b //int *p1=&a,*p2=&b; 定义时完成指向 printf(“\n %d,%d”,a,b);

printf(“\n %d,%d”, *p1,*p2);

}

注意:要区别定义和引用中的“ *”

Page 12: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

要特别注意以下用法的后果:

int *p;

*p=100;

程序将执行的命令:指针 p 所指向的整型变量所在的内存单元赋值100

p

Page 13: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:输入 a 和 b 两个整数,按先大后小的顺序输出 main()

{ int a,b,*p1, *p2, *p;

scanf(“%d,%d”,&a,&b); 1000 5 a

p1=&a; p2=&b; 1002 9 b

if(a<b)

{ p=p1; p1=p2; p2=p;}

printf(“\n %d,%d”,a,b); 2000 p1

printf(“\n%d,%d”,*p1,*p2); 2004 p2

} 2006 p

改变 p1和 p2的指向

1000

1002

1002

1000

Page 14: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

总结:

指针变量是专门用来存储变量地址的特殊变量

只要将某一变量的地址存入指针变量中,就可通过指针变量间接访问该变量。

为什么 C 语言要舍近求远来间接访问变量的内容呢?

Page 15: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■指针变量作为函数的参数 可将指针变量作函数的参数,接受实参地址,获得具体指向,进而通过指针变量间接访问主调函数的变量。

Page 16: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

swap(int *p1, int *p2)

{ int t;

t=*p1;

 *p1=*p2;

*p2=t; 1000 5 a

} 1002 9 b

main()

{ int a,b;

scanf(“%d,%d”,&a,&b); 2000 p1

if(a<b)swap(&a,&b); 2004 p2

printf(“\n %d,%d”,a,b); 2006 t

}

1000

1002

5

9

跨越逻辑上的限制

Page 17: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

swap(int p1, int p2) 不用指针变量情况 { int t;

t=p1;

  p1=p2;

p2=t; 1000 5 a

} 1002 9 b

main()

{ int a,b;

scanf(“%d,%d”,&a,&b); 2000 p1

if(a<b)swap(a, b); 2004 p2

printf(“\n %d,%d”,a,b); 2006 t

}

5

95

9

Page 18: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

重要概念:使用指针变量作函数参数,被调函数可以将多个结果交给主调函数。

Page 19: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:编写函数,求一元二次方程的两个实根。#include “math.h”

? root(float a,float b,float c, )

{ float d; d=b*b-4*a*c;

if(d<0||a==0)return(0);

? =(-b+sqrt(d))/2/a;

? =(-b-sqrt(d))/2/a;

return(1);

}

float *x1, float *x2

*x1 *x2

int

main()

{ int k; float a,b,c,x1,x2;

scanf(“%f,%f,%f”,&a,&b,&c);

k=root(a,b,c,&x1,&x2);

if(k) printf(“\n %f,%f”,x1,x2);

}

Page 20: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:求 n 个数的最大值、最小值和平均值。float aver(int a[], int n, int *max, int *min)

{ int i; float s=0;

*max=a[0]; *min=a[0];

for(i=0;i<n;i++)

{ s+=a[i];

if(a[i]>*max) *max=a[i];

if(a[i]<*min) *min=a[i];

}

return(s/100);

}

main()

{ int a[100],i,max,min;

float av;

for(i=0;i<100;i++)

scanf(“%d”,&a[i]);

av=aver(a,100,&max,&min);

printf(“ %d,%d,%f”,max,min,av);

}

Page 21: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

1. 指针,指针变量 : int *p,a;

初始化及引用 : p=&a; *p=1;

2. 指针变量作为函数参数 void swap(int *a,int*b){….}

int main(){

int a=9,b=8;

swap(&a,&b);

}

Page 22: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

8.3 数组的指针和指向数组的指针变量

数组有一个首地址 :

数组的指针。每个数组元素也都有地址 :

数组元素的指针。

5

3

2

1

6

8

7

4

2000

2002

2004

2006

int a[8];

Page 23: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■ 指向数组元素的指针变量 int a[10],*p;

p=a;

指向数组 p=&a[0];

指向数组元素

5

1

2

4

7

6

8

0

3

9

2000

2002

2004

2006

p

Page 24: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■ 通过指针引用数组元素 p=&a[0]; p 指向 a[0](下标变量 ) *p=1; 等效于 a[0]=1; 即可通过 p 来访问 a[0] 也可以通过 p 来访问其它元素: *(p+1)=3; 等 效 于 a[1]=3;(*(a+1)=3) 其中 p+1指向 a[1]

注意: p+1不是地址加 1 ,而是加一个数据类型单 位。 int a[10] ; int *p=a; *(p+1)=5;

Page 25: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

一般地 , 当 p 指向 a[0]时:p+i ∽ a+i ∽ &a[i]

*(p+i) ∽ *(a+i) ∽ a[i] ∽ p[i]

即以下几个语句等效:a[i]=10; *(p+i)=10; *(a+i)=10; p[i]=10;

Page 26: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:从键盘输入 10个数到数组 a :

int a[10],i,*p=a,s=0

for(i=0;i<10;i++) scanf(“%d”,&a[i]);

for(i=0;i<10;i++) scanf(“%d”,a+i);

for(i=0;i<10;i++) scanf(“%d”,p+i);

Page 27: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

累加求和的各种用法:for(i=0;i<10;i++)s+=a[i];

for(i=0;i<10;i++)s+=*(a+i);

for(i=0;i<10;i++)s+=*(p+i);

for(i=0;i<10;i++)s+=p[i];

for(i=0;i<10;i++)s+=*p++; 等效于 *(p++) ,右结合for(p=a;p<a+10;p++)s+=*p; 不能使用 a++

Page 28: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

使用指针变量访问数组时,要特别注意指针变量的当前值。 注意下例:  main()

{

int a[10],*p=a,i;

for(p=a;p<a+10;p++) scanf(“%d”,p);

 

for(i=0;i<10;i++)printf(“%d”,*p++);

}

p

p=a;

Page 29: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■ 数组名作为函数参数 有了指针概念的基础上,重新回顾数组名作为函数参数时,数据的传递情况:例:将数组 a 中的 n 个数按相反顺序存放。

Page 30: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

int inv(int x[], int n)

{ i,j,m,t; main()

m=(n-1)/2; {

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

{ j=n-1-i; 输入 a

t=x[i]; inv(a,10);

x[i]=x[j]; 输出 a

x[j]=t; }

}

}

a 与 x 共用同一片内存单元

ax1

2

3

4

5

6

7

8

9

10

m=4

i=0

j=9

Page 31: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

int inv(int *x, int n) 指针变量作函数参数时的传递情况

{ i,j,m,t; main()

m=(n-1)/2; {

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

{ j=n-1-i; 输入 a

t=x[i]; inv(a,10);

x[i]=x[j]; 输出 a

x[j]=t; }

} 下标法

}

a1000

1000x

{ j=n-1-i ; t=*(x+i); *(x+i)= *(x+j); *(x+j)=t; } 指针法

Page 32: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

进一步优化:int inv(int *x, int n)

{ main()

int *i=x,*j=x+n,t; {

for(;i<j;i++,j--) int a[10],i;

{ 输入 a

t=*i; inv(a,10);

*i=*j; 输出 a

*j=t; }

}

} 优点:简练 效率高

i

j

Page 33: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:选择法排序函数

void sort(int *a, int n)

{ int i,j,t;

for(i=0;i<n-1;i++)

for(j=i+1;j<n;j++)

if(a[i]>a[j]){t=a[i]; a[i]=a[j]; a[j]=t;}

} 只将形参改为指针变量,仍按下标法使用

void sort(int *a, int n)

{ int i,j,t;

for(i=0;i<n-1;i++)

for(j=i+1;j<n;j++)

if(*(a+i)>*(a+j))

{t=*(a+i); *(a+i)= *(a+j); *(a+j)=t;}

} 按指针法使用

选择法:首先选择最小的数放在 0 位置,再在剩下的数中选择最小的数放在下一位置,┈┈,

依次类推。

Page 34: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

进一步优化:void sort(int *a, int n)

{ int *i, *j,t;

for(i=a;i<a+n-1;i++)

for(j=i+1;j<a+n;j++)

if(*i>*j) {t=*i; *i=*j; *j=t;}

}

main()

{ int a[10],j;

for(j=0;j<10;j++)scanf(“%d”,a+j);

sort(a,10);

for(j=0;j<10;j++)printf(“%5d”,a[j]);

}

Page 35: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

分段排序?main()

{ int a[10],j;

for(j=0;j<10;j++)scanf(“%d”,a+j);

for(j=0;j<10;j++)printf(“%5d”,a[j]);

}

sort(a,5);

sort(a+5,5);

Page 36: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

数组名和指针的区别• 1. 数组名指代一种数据结构,这种数据结构就是数组;

 char str[10];  char *pStr = str; sizeof(str)=10; sizeof(pStr)=4( 平台32B);;;\ 

• 2. 数组名可以转换为指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;char str[10]; char *pStr = str;str++; //编译出错,提示 str不是左值 pStr++; //编译正确

Page 37: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

数组名和指针的区别• 3.数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;而且它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

•  void arrayTest(char str[]){    printf(“sizeof(str) =%d”,sizeof(str) ); // 输出指针长度 str++; // 编译正确 }

•  int main()  { char str1[10] = “Hello"; arrayTest(str1);      return 0;}

Page 38: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■ 指向多维数组的指针和指针变量 从本质上说,多维数组的指针与一维数组的指针相同,但在概念上和使用上,多维数组的指针要复杂些。 以二维数组的指针为例:

Page 39: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

●二维数组的地址 :一维: a , &a[i] , a+i 二维:

a , &a[i][j] , a+i ( 行指针 ) , a[i]( 特殊的一维数组元素,列指针 ) , a[i]+j a+i:只能指向第 i 行的第一个元素,行指针a[i]+j:只能指向第 i 行中的某一个元素,列指针

3 5 8 7

2 4 6 9

1 6 0 4

int a[3][4]

1000

1008

1016

a+0

a+1

a+2

a[0]

a[1]

a[2]

讨论以下用法的效果:for(i=0;i<3;i++) scanf(“%d”,a+i);输入数据: 1 2 3

讨论以下用法的效果:for(i=0;i<3;i++) scanf(“%d”,a[1]+i);输入数据: 1 2 3

讨论以下用法的效果:for(i=0;i<3;i++) scanf(“%d”,a[1]+i+1);输入数据: 1 2 3

讨论以下用法的效果:for(i=0;i<3;i++) scanf(“%d”,a+i+1);输入数据: 1 2 3

1

2

3

1 2 31 2 3

Page 40: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

注意:指针运算符 * 作用在行指针上的结果仍是指针 ----列指针 ; * 作用在列指针上的结果 --- 具体元素。

*(a+0) , *(a+1) , *(a+2) ——仍是地址。 *(a+i)

*(a[0]) , *(a[1]) , *(a[2]) —— 具 体 元 素值。 *(a[i])

*(a+i)+j 也是地址,但要区别:(a+i)+j—— 行指针 (a+1)+1 ?

*(a+i)+j——列指针 *(a+1)+1 ?

1000

1008

1016

a+0

a+1

a+2

a[0]

a[1]

a[2]

*(a+1)=1008

15

*(a[1])=15

Page 41: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

如果要通过 a+i形式的地址访问数组元素的具体内容,则:*(*(a+i)) 或 *(*(a+i)+j)

如: *(*(a+1)) —— a[1][0]

*(*(a+1)+2) —— a[1][2]

讨论: int a[3][3];

*(a+2)

*(*(a+1)+2)

*(a[1]+1)

*(*(a+1)+3)

1 2 3

4 5 6

7 8 9

Page 42: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:求数组 a 的所有元素之和。 可有多种用法:

for(i=0;i<3;i++) for(i=0;i<3;i++)for(j=0;j<4;j++) for(j=0;j<4;j++)s+=a[i][j]; s+=*(a[i]+j);

for(i=0;i<3;i++)for(j=0;j<4;j++) s+=*(*(a+i)+j);

Page 43: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

●指向二维数组的指针变量main(){ int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int i,k,*p; // int b[10];int *q=b; p=*a;//p=*(a+0);p=a[0];p=&a[0][0];(列指针变量) k=*p; k=*(p+2); for(p=*a;p<*a+2;p++)printf(“%3d”,*p); for(p=*a;p<*(a+1)+2;p++)printf(“%3d”,*p); for(p=*a;p<a[1]+2;p++)printf(“%3d”,*p); }

1 2 3 45 6 7 89 10 11 12

k=p[1][2]; 不合法k=*(*(p+1)+2);

k=p[1*4+2]; 合法k=*(p+1*4+2);

123456

12

123456

Page 44: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

●指向由 m 个元素组成的一维数组的指针变量 可以这样定义一个指针变量: int (*p)[4]

表示 p 为指向由 4 个整型数据组成的一维数组。注意不能省略 : ()int *p[4]; 具有 4 个指针类型数据的一维数组 int a[3][4]; 初始化: p=a+i; ( 行指针变量 )

p=a; 可通过 p 引用 a[i][j]: p[i][j] 或 *(*(p+i)+j)

Page 45: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:求矩阵的上三角元素之和。 main(){ int a[3][4],(*p)[4],i,j,s=0; 输入 a p=a; for(i=0;i<3;i++) for(j=i;j<4;j++) s+=p[i][j]; 或 s+=*(*(p+i)+j) printf(“\n %d”,s);}

Page 46: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

●多维数组的指针作函数参数 用于接受实参数组地址的形参可用两种:行指针和列指针。 以方阵转置为例: void at(int (*a)[3]) 用行指针 { int i,j,t; 缺点:不通用 for(i=0;i<3;i++) for(j=i+1;j<3;j++) { t=a[i][j]; a[i][j]=a[j][i]; a[j][i]=t; } }

Page 47: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

用列指针: void at(int *a,int n) { int i,j,t; for(i=0;i<n;i++) for(j=i+1;j<n;j++) { t=a[i*n+j]; a[i*n+j]=a[j*n+i]; a[j*n+i]=t; } } 优点:通用 在编通用函数时,一般使用列指针。

Page 48: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

8 . 4 字符串的指针和指向字符串的指针变量

■字符串的表示形式 可用两种方法访问字符串: ①用字符数组存放字符串 ②用字符指针指向一个字符串

Page 49: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

main(){ char c[5]=“abc”; 定义字符数组,并将字符串存入 char *p1=c,*p=“abc”; 定义指针变量,指向字符串 printf(“%s”,c); 通过数组名访问字符串

printf(“%s”,p); 通过指针变量访问字符串 printf(“%-c”,*(p+1)); 通过指针变量访问字符

}

c

a b c \0 a b c \0

1000

1000p

Page 50: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:字符串拷贝操作。main()

{ char a[]=“abcdef”,b[20]; int i;

for(i=0; *(a+i)!=’\0’; i++) *(b+i)=*(a+i);

*(b+i)=’\0’; printf(“%s”,b);

}

main()

{ char a[]=“abcdef”,b[20],*p1, *p2;

p1=a; p2=b;

for( ; *p1!=’\0’;p1++,p2++) *p2=*p1;

*p2=’\0’;

printf(“%s”,b);

}

用指针变量处理

Page 51: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

将拷贝操作编成一函数:void copy_string(char *from,char *to)

{

for(; *from; from++,to++) *to=*from;

*to=0;

}

还可以改成:void copy_string(char *from,char *to)

{

for(; *from;) *to++=*from++;

*to=0;

}

Page 52: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

字符串合并函数:void append_string(char *from,char *to){ for(;*to; to++); for(; *from;) *to++=*from++; *to=0; }

Page 53: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

阅读程序:void f (char *c) main()

{ {

c+=2; char c[20]=”abcdef”;

(*c)++; f(c+1);

c++; *c=0; printf(“%s”,c);

} }

 abce

Page 54: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

■内存空间的动态分配 在程序设计中,对于要处理的批量数据,我们往往是选用数组作为存放这些数据的数据结构,然而,数组有一个明显的缺点,就是在定义数组时,其长度必须是常值,无法根据需要动态地定义。这样,在很多情况下,不是定义的数组长度不够,就是定义太长以至于浪费。 采用动态分配可以克服这一缺点,并且可以随时释放。

Page 55: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

动态分配内存空间步骤: ①定义一指针变量。 ②申请一片内存空间,并将其首地址赋给指针变量。此时便可通过指针变量访问这片内存。 ③用完后释放这片内存空间。  int *p; p=malloc(byte); ……

free(p);

以上函数的原形在 stdio.h中。

p

Page 56: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

例:对 n 个学生的分数排序后输出。 #include “stdio.h”

void sort(int *a, int n) { ┈ }main(){ int *a,j,n; scanf(“%d”,&n); a=malloc(n*sizeof(int)); if(!a) exit(0); for(j=0;j<n;j++) scanf(“%d”,a+j); sort(a,n); for(j=0;j<n;j++) printf(“%5d”,a[j]); free(a);}

Page 57: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

函数的指针和指向函数的指针变量■用函数指针变量调用函数可以用指针变量指向一个函数,一个函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针。可以用指针变量指向函数,然后通过该指针变量调用此函数。

Page 58: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

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; 将 p 指向函数 max scanf(“%d%d”,&a,&b);

c=(*p)(a,b); 通过 p 调用函数 max 等效于c=max(a,b); printf(“\n %d”,c);

}

Page 59: 第 8 章 指针 指针 : C 的一个 重要概念 、 重要特色 。它使 C 具备了强大的功能,使 C 成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。

总结• 1. int *p ;• 2. swap ( *a,*b ) ;

• 3. int a[4],*p; p=a;

• 4. int a[3][4];

a, a+i, *(a+i), *(a+i)+j, a[i], a[i]+j;

• 5. int (*p)[4];

• 6. char *p=“C Programming”;