上一篇我们讲解了指针是什么和指针变量相关内容,这篇我们讲解指针和数组的故事。
一.数组名的理解
明白指针与数组之间的关系,我们先要明白数组名的到底是什么。
int arr[1,2,3,4,5];
arr
&arr[0]
arr表示的其实就是arr数组的首个元素的地址,说白了,数组名就是数组首个元素的地址。上述两个式子表示的都是一个东西。
但是数组名表示数组首个元素的地址这个是有两个例外的:
sizeof(arr);
&arr
sizeof(arr)中的数组名arr表示的是整个数组,我们可以通过输出该值来验证,如果输出该值的话是20(int 4个字节,数组有5个值)所以说我们求一个未知数组的长度是可以用sizeof(arr) / sizeof(arr[0]) 。
&arr取的也是整个数组,我们可以通过下发的代码来验证。
int main()
{
int arr[5] = { 1,2,3,4,5 };
printf("%p\n", &arr);
printf("%p\n", &arr + 1);
return 0;
}
//输出的结果
000000DF324FF618
000000DF324FF62C
我们在上一篇讲到指针与整数加减,加减的数是根据int*的类型来到,因此加1应该是加上4个字节,但是上述的结果并不是加上4个字节。通过计算,我们发现,它是直接将数组越过。
另外,数组的传参本质上也是讲数组的首元素地址传过去。所以传参的部分既可以写成数组的形式,也可以写成指针的形式。
二.使用指针访问数组
了解数组名后,我们可以进一步了解指针和数组的关系。指针是怎么访问数组的呢?
int a[5] = { 1,2,3,4,5 };
int* p = a;
for (int i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
使用上述的办法可以将数组里的每个元素打印出来,所以说 p[i] 其实等价于*(p+i)。其实编译器在处理时也是讲数组转化成指针,再去解引用的。我们可以拓展一下,[ ]这个符号是下标引用操作符,其实p[i]还可以写成i[p],对的,没错,这样写也行。因为编译器在编译的时候会讲数组名转换成指针形式,如上述的两个,转化完后是*(p+i)和*(i+p)其实没有什么区别,当然我们平时也没有必要用第二种解法,这里只做例子拓展。
三.二级指针与指针数组
二级指针说白了就是指向指针的指针。
int a[5] = { 1,2,3,4,5 };
int* p = a;
int** pp = &p;
pp存储的是指针p的地址,要也应用pp要解引用两次,*(*pp),*pp这个星号是取出了p的地址,对p在解引用才能求出a[0]的值。
指针数组,存储指针的数组。
int a1[] = { 1,2 };
int a2[] = { 3,4 };
int* a[] = { a1,a2 };
指针数组可以模拟二维数组。
int a1[] = { 1,2 };
int a2[] = { 3,4 };
int* a[] = { a1,a2 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%d ", a[i][j]);
}
}
为什么可以这样呢?那个a[i][j]其实就等于*(*(a+i)+j)所以说可以那样写先a+i解引用,再让解引用完的值加上j再解引用,这样就可以成功输出了。
以上就是本篇的全部内容了,创造不易,如果喜欢的话点个赞,点个关注^-^
谢谢大家^_^