1.数组名:数组名的值是一个指针常量,也就是第一个数组元素的地址。这里需要注意的是指针常量。编译器用数组名记录数组的信息(数组元素的个数等),只有在表达式中使用数组名才会产生一个指针常量。只存在两个特列:(1)sizeof(),返回的是数组的长度;(2)取地址操作符&,返回的是一个指向数组的指针.
int Array[5] = {1,2,3,4,5};
int *p = Array;
int *pArray = &Array;//区别在于p是数组Array[]第一个元素的地址,而*pArray是数组Array的地址
//若p 的值为 p = 0x804a014
// pArray = 0x804a014
// p + 1 = 0x804a018
// pArray + 1 = 0x804a028
2.下标的使用:C的下标与间接访问表达式一样,在任何使用下标引用的地方都可以使用对等的指针表达式来代替。
*(b + 3);//其中b是一个指向整型的指针,所以b+3指向另一个整型的指针,他所指向的是数组第一个元素向后移3个整数长度的位置。
int array[10];
int *ap = array +2;
则//ap,即为array+2,与&array[2]等价
//*ap,即为array[2]
//ap[0] ;貌似ap不是一个指针,其实这么想是错误的,c的下标引用与间接访问表达式是一样的,在这种情况下等价于*(ap + (0));
下面这段代码刚好可以解释上述问题
int main()
{
int Array[5] = { 1,2,3,4,5 };
int* p = Array;
printf("*(p+2) = %d\nArray[2] = %d\n(p+2)[2] = %d\n", *(p + 2), Array[2], (p + 2)[2]);
printf("p = %p\np + 1 = %p\n&Array = %p\n&Array + 1 = %p\n", p,p+1,&Array,&Array+1);
getchar();
return 0;
}
名称 | 值 | 类型 | 备注 |
---|---|---|---|
*(p + 2) | 3 | int | 等价于Array[2] |
Array[2] | 3 | int | |
(p + 2)[2] | 5 | int | 等价于Array[5] |
p | 0x0097f7f4 | int * | Array[0]的地址,是一个int型指针 |
p+1 | 0x0097f7f8 | int * | Array[1]的地址,是一个int型指针 |
&Array | 0x0097f7f4 {1, 2, 3, 4, 5} | int[5] * | &Array代表的是数组指针, |
&Array+1 | 0x0097f808 {-858993460, -1684265792, 9959460, 19865726, 1} | int[5] * | 因此,&Array+1表示向后移动5个int型字节 |
效率:数组与指针的效率问题
//代码段1
int Array[10],a;
for(a = 0; a < 10; a += 1)
Array[a] = 0;
//代码段2
int Array[10],*ap;
for(ap = Array; ap < Array; ap++)
*ap = 0;
指针的效率不低于数组,数组的效率不高于指针。如上述代码段1因为数组取元素是用下标乘以类型长度,执行的乘法运算,较为耗时;代码段2,循环中,执行乘法运算的都是1*4,结果这个乘法就在编译时执行过一次,——程序现在包含一条指令,把4与指针相加,而在运行时不执行乘法运算。因此在这种情况下指针效率比数组高。