紧接着上一篇指针的讲解,我们再来谈谈指针与数组的关系
首先,我们都知道数组在内存中是连续存放的,所以只要我们找到这个数组的首元素地址,是不是就可以找到整个数组呢?
答案是肯定的
//对于这个整形数组,它的首元素地址则是&arr[0]
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
数组名与首元素地址相同,可以得出结论:数组名表示的是数组首元素的地址
那么我们就可以这样写代码了 int *p = arr; //p存放的是数组首元素的地址
既然可以把数组名当作地址存放在一个指针里,那我们就可以使用指针来访问这个数组
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
int *p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("&arr[%d] = %p <==> p + %d = %p\n", i, &arr[i], i, p + i);
}
return 0;
}
我们可以从上面的例子看出来, p+i 计算的是数组 arr 下标为i的地址
那么我们就可以通过指针去访问数组
for (int i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
}
首先,你得知道指针数组是一个数组还是指针?
答案是数组,是一个存放指针的数组
我的上一篇讲指针的博客,就有提到,要理解指针要从四个方面理解,指针的类型、指针指向的类型、指针所指向的内存区、指针本身所占据的内存区。 我们重点看一下类型
这里
指针的类型:int* [6]
指针指向的类型:int*
arr是一个数组,有六个元素,每一个元素里是一个整形指针
既然指针数组,是数组,那数组指针毋庸置疑,肯定是指针了
能够指向数组的指针
[ ]优先级比*高
int (*arr)[6]
//arr先与*结合,说明arr是一个指针变量,指向一个大小为6个整型的数组
//所以arr是一个指针,指向一个数组,叫做指针数组
刚刚有提到过arr数组名表示的意义是首元素的地址,那&arr的意义是什么呢?
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr + 1);
printf("&arr+1= %p\n", &arr + 1);
return 0;
}
可以从上面的例子看出来,&arr 表示的是数组的地址,而不是数组首元素的地址。数组的地址+1,跳过整个数组的大小,对于&arr来说,与&arr+1的差值为40。
void print_arr1(int arr[3][5], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
//需要接受二维数组的地址,用一个数组指针
//把二维数组想象成一维数组
//arr相当于一维数组的首元素(每一行有三个元素)
void print_arr2(int(*arr)[5], int row, int col)
{
for (int i = 0; i < row; i++)
{
//arr+0 --->第一行 arr+1 --->第二行 ...
//arr+i 第i行的地址 *(arr+i) 第i行的元素
for (int j = 0; j < col; j++)
{
//*(arr+i)+j 第i行下标为j的地址 *(*(arr+i)+j) 访问第i行下标为j的元素
printf("%d ", *(*(arr + i) + j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10 };
print_arr1(arr, 3, 5);
print_arr2(arr, 3, 5);
return 0;
}
//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
总结: 数组名的意义: