一、数组元素的指针的定义:
所谓数组元素的指针就是数组元素的地址。
我们可以这样理解,先前我们说到,指针就是变量的地址。
那么数组是可以包含多个元素的,每一个变量在内存中都会占用空间,就用有相应的地址。
所以,数组元素的指针,就是记录了数组中各个元素的地址。
当然,不可能一次性记录完,而是通过数据在内存中的存储规律,
通过给定义一个数组元素初始的地址,根据计算获得该数组中的其它地址
举例:
int a[10] = {1,3,5,7,9,11,13,15,17,19};
int *p;
p = &a[0];
p = a;
上面的例子中,我们定义了一个数组和一个指针
然后,我们将该数组中第一个元素的地址 赋值给指针变量p。
所以指针p就指向a[0] 这个地址。
在数组中,单独的数组变量名代表的数组第一个元素的地址
所以说 a = &a[0]
那么,我们也可以用 p = a 来获得一个数组元素的地址
当然,我们在定义指针的时候,可以进行初始化的。
如: int *p =a; 它的作用是a数组的首元素地址赋值给了指针变量p,而不是赋值给了 *p
总之,记住一点,指针是表示地址的,指针变量表示的是地址的值
二、在引用数组元素指针的运算
我们提到指针就是地址,对地址进行赋值运算时没有问题的,但是算数运算呢?
+ - * /
首先对地址的*、/ 是没有意义的,因为得到的东西是没有任何意义的。
那么 +、- 呢?
例:int a[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = a;
此时,p是 a[0]的地址 ,那么p+1 就是a[1]的地址了。
当然,它在真正编译的时候,p+1所代表的地址是 p+1*d , d是一个数组元素所占的字节数
如下:
#include <stdio.h> int main(){ int a[10] = {1,2,3,4,5,6,7,8,9,0}; int *p = a; printf("p的初始地址是%d:\n",p); printf("p的值是%d:\n",*p); p++; printf("p++的初始地址是%d:\n",p); printf("p++的值是%d:\n",*p); p = p+3; printf("p+3的初始地址是%d:\n",p); printf("p+3的值是%d:\n",*p); }
结果:
p的初始地址是2293520: p的值是1: p++的初始地址是2293524: p++的值是2: p+3的初始地址是2293536: p+3的值是5: 请按任意键继续. . .
三、通过指针引用数组元素
(1)下标法:如a[i] 形式
(2)指针法: 如*(a+i) 或 *(p+i)。其中a是数组名,p是指向数组元素的指针的指针变量,其初值p=a。
举例说明:
例:有一个整型数组a,有10个元素,要求输出数组中的全部元素。
(1)下标法:
#include <stdio.h> int main(){ int a[10]; int i; printf("please enter 10 integer numbers:"); for(i=0;i<10;i++) scanf("%d",&a[i]); for(i=0;i<10;i++) printf("%d ",a[i]); printf("%\n"); return 0; }
(2)通过数组名计算数组元素地址,找出元素的值。
#include <stdio.h> int main(){ int a[10]; int i; printf("please enter 10 integer numbers:"); for(i=0;i<10;i++){ scanf("%d",&a[i]); } for(i=0;i<10;i++){ printf("%d ",*(a+i)); } printf("\n"); return 0; }
(3)用指针变量指向数组元素
#include <stdio.h> int main(){ int a[10]; int *p,i; printf("please enter 10 integer numbers:"); for(i=0;i<10;i++) scanf("%d",&a[i]); for(p=a;p<a+10;p++) printf("%d ",*p); printf("\n"); return 0; }
在上述的三个例子中,我们分别用了下标法、指针法来控制输出的变量。
首先,下标法用的是我们最熟悉的数组下标,即a[i],前面 通过循环来改变i下标值的大小 ,并通过下标法来输出存放在数组中的变量。
指针法分别用了两种不用的形式,一个是直接用数组变量名,比如a,a代表数组的首地址,则*a是数组首地址的值,那么随着下标的递增,*(a+i) 就是 数组a的第i个值。
这里需要注意的是,数组a 是指针型常量,所以 如果用a++ 来移动指针,用*a来获得指针所指向的值,这种方法是不行的。
如下:
for(p=a;a<(p+10);a++)
printf("%d",*a);
程序会报wrong type argument to increment 错误 ,
所以我们只要 记住 ,数组的变量是 指针型常量,它是无法通过自增 来改变 地址的位置的。
对于第三个例子,我们用一个指针变量指向 该数组,因为该指针变量不是常量,所以它可以递增。
当使用p=a ,p++;时 ,它的位置会指向下一个数组元素的位置。
所以,我们可以直接用 *p 来获取该指针所指向数组的 元素。
在第三个例子中,我们也用的数组下标地址的方式来存取需要输入的数字,
现在,我们将scanf方法也改成指针的方式:
#include <stdio.h> int main(){ int a[10]; int *p,i; printf("please enter 10 integer numbers:"); for(p=a;p<(a+10);p++) scanf("%d",p); for(p=a;p<(a+10);p++) printf("%d ",*p); printf("\n"); return 0; }
下面,我们给出一个指针和 变量同时使用的例子
例:通过指针变量输出整型数组a的10个元素。
#include <stdio.h> int main(){ int *p,i,a[10]; p = a; printf("please enter 10 integer numbers:"); for(i=0;i<10;i++) scanf("%d",p++); for(i=0;i<10;i++,p++) printf("%d",*p); printf("\n"); return 0; }
上面的例子中,我们发现,结果并不是我们想要的数据,这其中主要原因就是,p所指向的地址不正确,
在第一个for循环体中,经过10轮循环,p指向的位置是数组第10个元素的地址,
所以 ,在第二个for循环中,p指向的是 数组第11-20的地址,当然,这些地址的值是不存在的,所以输出的结果也是不正确的。
那么我们如何解决这个问题的, 解决办法就是,在第二次for循环的开始,让p重新指向数组的初始位置
即p=a
我们看下面例子:
#include <stdio.h> int main(){ int *p,i,a[10]; p = a; printf("please enter 10 integer numbers:"); for(i=0;i<10;i++) scanf("%d",p++); p = a; for(i=0;i<10;i++,p++) printf("%d ",*p); printf("\n"); return 0; }
由于*p++ 是右运算符,所以,上述的程序又可以改成
#include <stdio.h> int main(){ int *p,i,a[10]; p = a; printf("please enter 10 integer numbers:"); for(i=0;i<10;i++) scanf("%d",p++); p = a; for(i=0;i<10;i++,p) printf("%d ",*p++); printf("\n"); return 0; }