当前位置:松语文学 > 其他类型 >C语言设计最新章节 > C语言设计TXT下载
错误举报

第 20 章

  /*指针变量赋值*/

  pmin=&a;}            /*指针变量赋值*/

  if(c>*pmax) pmax=&c;       /*判断并赋值*/

  if(c<*pmin) pmin=&c;       /*判断并赋值*/

  printf("max=%d\nmin=%d\n",*pmax,*pmin); /*输出结果*/

  }

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

  一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,

  它们都有相应的地址。所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的

  地址。

  10.3.1 指向数组元素的指针

  一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址。一

  个数组也是由各个数组元素(下标变量)组成的。每个数组元素按其类型不同占有几个连续的

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址。

  定义一个指向数组元素的指针变量的方法,与以前介绍的指针变量相同。

  例如:

  int a[10];  /*定义 a 为包含 10 个整型数据的数组*/

  int *p;   /*定义 p 为指向整型变量的指针*/

  应当注意,因为数组为 int 型,所以指针变量也应为指向 int 型的指针变量。下面是对

  指针变量赋值:

  p=&a[0];

  把 a[0]元素的地址赋给指针变量 p。也就是说,p 指向 a 数组的第 0 号元素。

  C 语言规定,数组名代表数组的首地址,也就是第 0 号元素的地址。因此,下面两个语

  句等价:

  p=&a[0];

  p=a;

  在定义指针变量时可以赋给初值:

  int *p=&a[0];

  它等效于:

  int *p;

  p=&a[0];

  当然定义时也可以写成:

  int *p=a;

  从图中我们可以看出有以下关系:

  p,a,&a[0]均指向同一单元,它们是数组 a 的首地址,也是 0 号元素 a[0]的首地址。应

  该说明的是 p 是变量,而 a,&a[0]都是常量。在编程时应予以注意。

  数组指针变量说明的一般形式为:

  类型说明符 *指针变量名;

  其中类型说明符表示所指数组的类型。从一般形式可以看出指向数组的指针变量和指向普通

  变量的指针变量的说明是相同的。

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  10.3.2 通过指针引用数组元素

  C 语言规定:如果指针变量 p 已指向数组中的一个元素,则 p+1 指向同一数组中的下一

  个元素。

  引入指针变量后,就可以用两种方法来访问数组元素了。

  如果 p 的初值为&a[0],则:

  1) p+i 和 a+i 就是 a[i]的地址,或者说它们指向 a 数组的第 i 个元素。

  2) *(p+i)或*(a+i)就是 p+i 或 a+i 所指向的数组元素,即 a[i]。例如,*(p+5)或*(a+5)

  就是 a[5]。

  3) 指向数组的指针变量也可以带下标,如 p[i]与*(p+i)等价。

  根据以上叙述,引用一个数组元素可以用:

  1) 下标法,即用 a[i]形式访问数组元素。在前面介绍数组时都是采用这种方法。

  2) 指针法,即采用*(a+i)或*(p+i)形式,用间接访问的方法来访问数组元素,其中 a

  是数组名,p 是指向数组的指针变量,其处值 p=a。

  【例 10.9】输出数组中的全部元素。(下标法)

  main(){

  int a[10],i;

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

  a[i]=i;

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

  printf("a[%d]=%d\n",i,a[i]);

  }

  【例 10.10】输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)

  main(){

  int a[10],i;

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

  *(a+i)=i;

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

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  printf("a[%d]=%d\n",i,*(a+i));

  }

  【例 10.11】输出数组中的全部元素。(用指针变量指向元素)

  main(){

  int a[10],I,*p;

  p=a;

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

  *(p+i)=i;

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

  printf("a[%d]=%d\n",i,*(p+i));

  }

  【例 10.12】

  main(){

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

  for(i=0;i<10;){

  *p=i;

  printf("a[%d]=%d\n",i++,*p++);

  }

  }

  几个注意的问题:

  1) 指针变量可以实现本身的值的改变。如 p++是合法的;而 a++是错误的。因为 a 是数组

  名,它是数组的首地址,是常量。

  2) 要注意指针变量的当前值。请看下面的程序。

  【例 10.13】找出错误。

  main(){

  int *p,i,a[10];

  p=a;

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

  *p++=i;

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

  printf("a[%d]=%d\n",i,*p++);

  }

  【例 10.14】改正。

  main(){

  int *p,i,a[10];

  p=a;

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

  *p++=i;

  p=a;

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

  printf("a[%d]=%d\n",i,*p++);

  }

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  3) 从上例可以看出,虽然定义数组时指定它包含 10 个元素,但指针变量可以指到数组以

  后的内存单元,系统并不认为非法。

  4) *p++,由于++和*同优先级,结合方向自右而左,等价于*(p++)。

  5) *(p++)与*(++p)作用不同。若 p 的初值为 a,则*(p++)等价 a[0],*(++p)等价 a[1]。

  6) (*p)++表示 p 所指向的元素值加 1。

  7) 如果 p 当前指向 a 数组中的第 i 个元素,则

  *(p--)相当于 a[i--];

  *(++p)相当于 a[++i];

  *(--p)相当于 a[--i]。

  10.3.3 数组名作函数参数

  数组名可以作函数的实参和形参。如:

  main()

  {int array[10];

  ……

  ……

  f(array,10);

  ……

  ……

  }

  f(int arr[],int n);

  {

  ……

  ……

  }

  array 为实参数组名,arr 为形参数组名。在学习指针变量之后就更容易理解这个问题

  了。数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址,形参得

  到该地址后也指向同一数组。这就好象同一件物品有两个彼此不同的名称一样。

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  同样,指针变量的值也是地址,数组指针变量的值即为数组的首地址,当然也可作为函

  数的参数使用。

  【例 10.15】

  float aver(float *pa);

  main(){

  float sco[5],av,*sp;

  int i;

  sp=sco;

  printf("\ninput 5 scores:\n");

  for(i=0;i<5;i++) scanf("%f",&sco[i]);

  av=aver(sp);

  printf("average score is %5.2f",av);

  }

  float aver(float *pa)

  {

  int i;

  float av,s=0;

  for(i=0;i<5;i++) s=s+*pa++;

  av=s/5;

  return av;

  }

  【例 10.16】将数组 a 中的 n 个整数按相反顺序存放。

  算法为:将 a[0]与 a[n-1]对换,再 a[1]与 a[n-2] 对换 ……,直到将 a[(n-1/2)]与

  a[n-int((n-1)/2)]对换。今用循环处理此问题,设两个“位置指示变量”i 和 j,i 的初值为

  0,j 的初值为 n-1。将 a[i]与 a[j]jiāo换,然后使 i 的值加 1,j 的值减 1,再将 a[i]与 a[j]

  jiāo换,直到 i=(n-1)/2 为止,如图所示。

  程序如下:

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  void inv(int x[],int n)  /*形参x是数组名*/

  {

  int temp,i,j,m=(n-1)/2;

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

  {j=n-1-i;

  temp=x[i];x[i]=x[j];x[j]=temp;}

  return;

  }

  main()

  {int i,a[10]={3,7,9,11,0,6,7,5,4,2};

  printf("The original array:\n");

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

  printf("%d,",a[i]);

  printf("\n");

  inv(a,10);

  printf("The array has benn inverted:\n");

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

  printf("%d,",a[i]);

  printf("\n");

  }

  对此程序可以作一些改动。将函数 inv 中的形参 x 改成指针变量。

  【例 10.17】对例 10.16 可以作一些改动。将函数 inv 中的形参 x 改成指针变量。

  程序如下:

  void inv(int *x,int n)  /*形参x为指针变量*/

  {

  int *p,temp,*i,*j,m=(n-1)/2;

  i=x;j=x+n-1;p=x+m;

  for(;i<=p;i++,j--)

  {temp=*i;*i=*j;*j=temp;}

  return;

  }

  main()

  {int i,a[10]={3,7,9,11,0,6,7,5,4,2};

  printf("The original array:\n");

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

  printf("%d,",a[i]);

  printf("\n");

  inv(a,10);

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  printf("The array has benn inverted:\n");

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

  printf("%d,",a[i]);

  printf("\n");

  }

  运行情况与前一程序相同。

  【例 10.18】从 0 个数中找出其中最大值和最小值。

  调用一个函数只能得到一个返回值,今用全局变量在函数之间“传递”数据。程序如下:

  int max,min;   /*全局变量*/

  void max_min_value(int array[],int n)

  {int *p,*array_end;

  array_end=array+n;

  max=min=*array;

  for(p=array+1;p<array_end;p++)

  if(*p>max)max=*p;

  else if (*p<min)min=*p;

  return;

  }

  main()

  {int i,number[10];

  printf("enter 10 integer umbers:\n");

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

  scanf("%d",&number[i]);

  max_min_value(number,10);

  printf("\nmax=%d,min=%d\n",max,min);

  }

  说明:

  1) 在函数 max_min_value 中求出的最大值和最小值放在 max 和 min 中。由于它们是全局,

  因此在主函数中可以直接使用。

  2) 函数 max_min_value 中的语句:

  max=min=*array;

  array 是数组名,它接收从实参传来的数组 numuber 的首地址。

  *array 相当于*(&array[0])。上述语句与 max=min=array[0];等价。

  3) 在执行 for 循环时,p 的初值为 array+1,也就是使 p 指向 array[1]。以后每次执行 p++,

  使 p 指向下一个元素。每次将*p 和 max 与 min 比较。将大者放入 max,小者放 min。

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  4) 函数 max_min_value 的形参 array 可以改为指针变量类型。实参也可以不用数组名,而

  用指针变量传递地址。

  【例 10.19】程序可改为:

  int max,min;   /*全局变量*/

  void max_min_value(int *array,int n)

  {int *p,*array_end;

  array_end=array+n;

  max=min=*array;

  for(p=array+1;p<array_end;p++)

  if(*p>max)max=*p;

  else if (*p<min)min=*p;

  return;

  }

  main()

  {int i,number[10],*p;

  p=number;       /*使p指向number数组*/

  printf("enter 10 integer umbers:\n");

  for(i=0;i<10;i++,p++)

  scanf("%d",p);

  p=number;

  max_min_value(p,10);

  printf("\nmax=%d,min=%d\n",max,min);

  }

  归纳起来,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关

  系有以下4种:

  1) 形参和实参都是数组名。

  main()

  {int a[10];

  ……

  f(a,10)

  ……

  }

  a和x指的是同一组数组。

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

  main()

  {int a[10];

  ……

  f(a,10)

  ……

  }

  3) 实参、型参都用指针变量。

  4) 实参为指针变量,型参为数组名。

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  f(int x[],int n)

  {

  ……

  }

  f(int *x,int n)

  {

  ……

  }

  【例 10.20】用实参指针变量改写将 n 个整数按相反顺序存放。

  void inv(int *x,int n)

  {int *p,m,temp,*i,*j;

  m=(n-1)/2;

  i=x;j=x+n-1;p=x+m;

  for(;i<=p;i++,j--)

  {temp=*i;*i=*j;*j=temp;}

  return;

  }

  main()

  {int i,arr[10]={3,7,9,11,0,6,7,5,4,2},*p;

  p=arr;

  printf("The original array:\n");

  for(i=0;i<10;i++,p++)

  printf("%d,",*p);

  printf("\n");

  p=arr;

  inv(p,10);

  printf("The array has benn inverted:\n");

  for(p=arr;p<arr+10;p++)

  printf("%d,",*p);

  printf("\n");

  }

  注意:main 函数中的指针变量 p 是有确定值的。即如果用指针变作实参,必须现使指针变

  量有确定值,指向一个已定义的数组。

  【例 10.21】用选择法对 10 个整数排序。

  main()

  谭浩强   C 语言程序设计        2001 年 5 月 1 日

  {int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};

  printf("The original array:\n");

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

  printf("%d,",a[i]);

  printf("\n");

  p=a;

  sort(p,10);

  for(p=a,i=0;i<10;i++)

  {printf("%d ",*p);p++;}

  printf("\n");

  }

  sort(int x[],int n)

  {int i,j,k,t;

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

  {k=i;

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

  if(x[j]>x[k])k=j;

  if(k!=i)

  {t=x[i];x[i]=x[k];x[k]=t;}

  }

  }

  说明:函数 sort 用数组名作为形参,也可改为用指针变量,这时函数的首部可以改为:

  sort(int *x,int n) 其他可一律不改。

  10.3.4 指向多维数组的指针和指针变量

  本小节以二维数组为例介绍多维数组的指针变量

  松语文学免费小说阅读_www.16sy.com