C语言设计

第37章


例如:
    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 ",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 ",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 ",i,*(p+i));
}
【例 10.12】
main(){
  int a[10],i,*p=a;
  for(i=0;i<10;){
    *p=i;
    printf("a[%d]=%d ",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 ",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 ",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(" input 5 scores: ");
  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]交换,然后使 i 的值加 1,j 的值减 1,再将 a[i]与 a[j]
交换,直到 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: ");
 for(i=0;i<10;i++)
   printf("%d,",a[i]);
 printf(" ");
 inv(a,10);
 printf("The array has benn inverted: ");
 for(i=0;i<10;i++)
  printf("%d,",a[i]);
 printf(" ");
}
对此程序可以作一些改动。
小说推荐
返回首页返回目录