1、两种情况下,一维数组不是指向数组首元素地址的指针
1. int arr[5] = { 1, 2, 3, 4, 5 }; 2. 3. //除了两种特殊情况下,一维数组名称都是指针首元素的地址 4. //特殊情况1: 对数组名称 进行sizeof 5. printf("sizeof arr = %d\n", sizeof (arr)); //20 6. 7. //特殊情况2: 对数组名称 取地址 8. //int * p = &arr; //这里会报错,因为p的类型时int *, arr的类型时int (*)[5] 9. printf("%d\n", &arr); 10. printf("%d\n", &arr + 1); //可以看到两次输出的地址相差20,也就是整个数组的大小
这里看一个经典的题目, 数组名a与&a的理解
1. #include <stdio.h> 2. 3. int main() 4. 5. { 6. 7. int a[5]={1,2,3,4,5}; 8. 9. int* ptr=(int*)(&a+1); 10. 11. printf("%d,%d",*(a+1),*(ptr-1)); 12. 13. 14. system("pause"); 15. 16. return 0; 17. }
答案:2,5
解析:
int* ptr=(int*)(&a+1);&a为数组a的首地址,对指针加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1,所以&a+1则为&a的首地址加5*sizeof(int),显然当前指针已经超过了数组的界限。将上一步计算出来的地址,强制转换成int*类型,赋给ptr。
*(a+1);a,&a的值是一样的,但意思不一样。a是数组首元素的首地址,也就是[0]的首地址,a+1是数组下一个元素的首地址,即a[1],&a+1是下一个数组的首地址。所以输出2
*(ptr-1);因为ptr是指向a[5],并且ptr是int*类型,所以*(ptr-1)是指向a[4],输出5。
2、除了两种特殊情况外,都是指向数组中首元素的地址的指针
1. int * p = arr; 2. p = p + 3; 3. // []里面可不可以放负数 可以!! 4. printf("%d\n", p[-1]); 5. printf("%d\n", *(p - 1));
从这个例子中也可以看出,访问数组元素的时候,下标可以是负数
3、数组名--- 指针常量,指针的指向不可以修改
int arr[] = {1, 3, 5, 7, 9}; //数组名做指针的解读的时候,int * const arr;
4、int[] 与int *是等价的
1. void printArray( int arr[], int len )// int arr[] 等价于 int * arr 2. { 3. for (int i = 0; i < len;i++) 4. { 5. //printf("%d\n", arr[i]); // 给人看 6. 7. printf("%d\n", *(arr + i)); //给机器看 8. 9. } 10. 11. }