素。数组的基地址是在内存中存储数组的起始位置,它是数组中第1个元素(下标为0)的地 址。在表达形式上,数组名本身就是一个地址,其值就是数组的基地址,是一个确定的值, 可以把它看做常量指针。假设给出如下定义: int a[10],*p; 假定系统分别把编号为1245016,1245020,1245024,.等内存字节作为数组元素a0], a1],a[2]..直到a[9]的地址,那么其中内存位置1245016是数组a的基地址,也是数组元 素a0]的地址,而数组名a的值也是1245016,它是一个地址常量。下面2条语句是等价的: p-a; p=&a0]: 它们都把1245016这个地址值赋给了指针变量p。 特别需要注意的是,数组名是常量,不能对它赋值。 2.通过指针操作数组元素的方法 如果将一个数组的基地址赋给了一个指针变量,那么对于数组的操作,除了可以使用常 规的下标来操作数组元素,还可以使用指针。 示例: #include <stdio.h> void main(void) inta[10]={1,2,3,4,5,6,7,8,9,10},sum,*p: sum=0; for(p=a;p<=a+9;p++) sum +=*p; printf("这l0个数组元素的和是:%dn",sum; 该示例是通过指针对数组元素求和。在循环中,指针变量p的初值是数组a的基地址,p 连续取值a,a+l,a+2,.,a+9。请注意,此处a+1就是数组元素al]的地址,a+2就是数组 元素a[2]的地址,以此类推。一般而言,如果i是int型变量,那么p+i就是距地址p的第i 个偏移,类似地,a+i是距离数组a的基地址的第i个偏移,*(a+i)与a[等价。下面是对数组 元素求和的第二种方法: -177-
素。数组的基地址是在内存中存储数组的起始位置,它是数组中第 1 个元素(下标为 0)的地 址。在表达形式上,数组名本身就是一个地址,其值就是数组的基地址,是一个确定的值, 可以把它看做常量指针。假设给出如下定义: int a[10],*p; 假定系统分别把编号为 1245016,1245020,1245024,……等内存字节作为数组元素 a[0], a[1],a[2]……直到 a[9]的地址,那么其中内存位置 1245016 是数组 a 的基地址,也是数组元 素 a[0]的地址,而数组名 a 的值也是 1245016,它是一个地址常量。下面 2 条语句是等价的: p=a; p=&a[0]; 它们都把 1245016 这个地址值赋给了指针变量 p。 特别需要注意的是,数组名是常量,不能对它赋值。 2. 通过指针操作数组元素的方法 如果将一个数组的基地址赋给了一个指针变量,那么对于数组的操作,除了可以使用常 规的下标来操作数组元素,还可以使用指针。 示例: #include <stdio.h> void main(void) { int a[10]={1,2,3,4,5,6,7,8,9,10},sum,*p; sum=0; for(p=a;p<=a+9;p++) sum += *p; printf("这 10 个数组元素的和是:%d \n",sum); } 该示例是通过指针对数组元素求和。在循环中,指针变量 p 的初值是数组 a 的基地址,p 连续取值 a,a+1,a+2,…,a+9。请注意,此处 a+1 就是数组元素 a[1]的地址,a+2 就是数组 元素 a[2]的地址,以此类推。一般而言,如果 i 是 int 型变量,那么 p+i 就是距地址 p 的第 i 个偏移,类似地,a+i 是距离数组 a 的基地址的第 i 个偏移,*(a+i)与 a[i]等价。下面是对数组 元素求和的第二种方法: - 177 -
sum=0; for(i=0;i<=9;i++) sum+=*(ati); 仔细阅读下面的示例程序,并输入到VC中编译、运行,查看程序的输出结果。该程序演 示了指针与数组之间的关系,其中也使用了指针来操作数组元素。 示例: #include <stdio.h> void main(void) inta10={1,2,3,4,5,6,7,8,9,10; int i,*p; for(i=0:i<=9:i++) printf("使用下标输出数组元素,元素地址:%d,值:%dn",&a[i,ai): for(p-a;p<-a+9;p++) printf("使用指针输出数组元素,元素地址:%d,值:%dn",p,*p)方 } 3.数组名作为函数参数 在函数定义中,被声明为数组的形式参数实际上是一个指针,调用时的实际参数则直接 用一个数组名即可,当传递数组时,实际上传递的是数组的基地址,数组元素本身不被复制。 示例: #include <stdio.h> void main(void) inti,a[10]={10,9,8,7,6,5,4,3,2,1},n=10: int sum(int a,int n); void reverse(int p[]int n); printf("这些数组元素的和是:%dn",sum(a,l0),/调用求和函数,并输出 reverse(a,n); ∥调用逆序函数 -178-
sum=0; for(i=0;i<=9;i++) sum += *(a+i); 仔细阅读下面的示例程序,并输入到 VC 中编译、运行,查看程序的输出结果。该程序演 示了指针与数组之间的关系,其中也使用了指针来操作数组元素。 示例: #include <stdio.h> void main(void) { int a[10]={1,2,3,4,5,6,7,8,9,10}; int i,*p; for (i=0;i<=9;i++) printf("使用下标输出数组元素,元素地址:%d ,值:%d \n",&a[i],a[i]); for(p=a;p<=a+9;p++) printf("使用指针输出数组元素,元素地址:%d ,值:%d \n",p,*p); } 3. 数组名作为函数参数 在函数定义中,被声明为数组的形式参数实际上是一个指针,调用时的实际参数则直接 用一个数组名即可,当传递数组时,实际上传递的是数组的基地址,数组元素本身不被复制。 示例: #include <stdio.h> void main(void) { int i, a[10]={10,9,8,7,6,5,4,3,2,1},n=10; int sum(int a[],int n); void reverse(int p[ ], int n); printf("这些数组元素的和是:%d\n",sum(a,10)); //调用求和函数,并输出 reverse(a, n); // 调用逆序函数 - 178 -
for(i=0;i<n;i++) printf("%d\t",afi]), } /体定义sum函数:使用数组作为函数参数实现求和*/ int sum(int a,int n) { int i.s=0: for(i=0;i<=n-1;i++) s+=ali]; return s; } /体定义reverse函数:使用数组作为函数参数实现逆序存放*/ void reverse(int all,int n) int i,j,t; for(i=0,j=n-1;i<j;i++jj--) t=afi]; a]aljl; a]=t } } 该示例中,sum函数将数组a作为参数,返回的是该数组的所有元素的和(通过return返 回):reverse函数表面上看虽然没有用return返回值,但是它直接在函数中改变了数组a中各 个元素的值,实现了元素的逆序存放,并且这个改变在main函数中仍然有效。 4.通过指针操作字符串 字符串常量通常被看做一个特殊的一维字符数组,与数组的存储类似,字符串常量中的 所有字符在内存中连续存放。存放这些字符的起始地址,即存放字符串常量首字母的存储单 元的地址,称为字符串常量的值。也就是说,字符串常量实质上是一个指向该字符串首字符 -179-
for(i = 0; i < n; i++) printf("%d\t", a[i]); } /* 定义 sum 函数:使用数组作为函数参数实现求和 */ int sum(int a[],int n) { int i,s=0; for(i=0;i<=n-1;i++) s += a[i]; return s; } /* 定义 reverse 函数:使用数组作为函数参数实现逆序存放 */ void reverse(int a[], int n) { int i, j, t; for(i=0,j=n-1;i<j;i++,j--) { t = a[i]; a[i] = a[j]; a[j] = t; } } 该示例中,sum 函数将数组 a 作为参数,返回的是该数组的所有元素的和(通过 return 返 回);reverse 函数表面上看虽然没有用 return 返回值,但是它直接在函数中改变了数组 a 中各 个元素的值,实现了元素的逆序存放,并且这个改变在 main 函数中仍然有效。 4. 通过指针操作字符串 字符串常量通常被看做一个特殊的一维字符数组,与数组的存储类似,字符串常量中的 所有字符在内存中连续存放。存放这些字符的起始地址,即存放字符串常量首字母的存储单 元的地址,称为字符串常量的值。也就是说,字符串常量实质上是一个指向该字符串首字符 - 179 -