目录
数组名的理解
上一篇文章我们提到,数组名就是数组首元素的地址,但存在特殊情况不满足这个关系
特殊情况
1.sizeof(数组名)
此时的数组名表示的是一整个数组,以字节为单位计算整个数组的大小
举例
#include <stdio.h>
int main()
{
int a[1] = { 0 };
int b[10] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(b));
return 0;
}
在上面可以看到,在数组大小不同时,打印出来的内容也根据数组大小有所不同
2.&数组名
&数组名时,取出的地址是整个数组的地址
举例
#include <stdio.h>
int main()
{
int a[10] = { 0 };
printf(" a=%p a+1=%p\n", a,a+1);
printf("a[0]=%p a[0]+1=%p\n", &a[0],&a[0]+1);
printf(" &a=%p &a+1=%p\n", &a, &a + 1);
return 0;
}
在上面的代码中,我们分别打印了三种不同情况下的地址
可以看到a,&a[0],&a的地址都是一样的
但是他们在进行计算时,每一步经过的字节就会有差别
a和&a[0]走一步的大小是一样的,都是一个int型数据的大小(4字节)
但&a时,走一步却直接跨过了一整个数组,这是因为&a时取出的地址是整个数组的地址,因此计算时走一步就会直接跨越一整个数组
数组是一块连续的空间,而指针变量只是一个4或8字节的变量
除了上面两个特殊情况,其他情况下都是数组名都是数组首元素的地址
所以在实际写代码时 arr[i] = *(arr+i)
同时,*(arr+i) = *(i+arr),由此我们可以延伸得到arr[i] = i[arr]
这是因为【】是下标引用操作符,所以arr[i]=*(arr+i)=*(i+arr)=i[arr]
但在实际应用中尽量不要用i[arr]这种反直觉的写法!!!
数组传参
本质
数组传参就是传递数组首元素的地址,因此形参访问的数组和实参的数组是同一个
形参的数组不会再次创建数组空间,所以形参的数组可以忽略数组大小
举例:我们想要求一个数组的个数
#include <stdio.h>
void print(int a[10])
{
int sz = sizeof(a)/sizeof(a[0]);
printf("%d", sz);
}
int main()
{
int a[10] = { 0 };
print(a);
return 0;
}
在上面的代码中,我们试图在print函数中求数组的个数
但是由于数组传参的本质是传递数组首元素地址的指针
所以sizeof(a)就是8(个字节)(在64位环境下,若在32位环境下则是4个字节)
我们就无法求出数组的真正大小
二级指针
概念
在前面我们所用的都是一级指针(int*)
我们知道,一级指针存放的是数据的地址,那么此时我们再用一个指针存放这个一级指针的地址,
存放一级指针地址的指针就是二级指针,写作int**
PS:类似于俄罗斯套娃,二级指针--->一级指针-->数据
举例
#include <stdio.h>
int main()
{
int a = 0;
int* p1 = &a;
int** p2 = &p1;
return 0;
}
结合上面代码让我们先回顾一下一级指针的符号含义:
*代表p1是一个指针,int是说明p1指向的类型为int型
同理我们来看二级指针的符号含义:
右边的*代表p2是一个指针,左边的int*说明p2指向的类型为int*型
三级指针就是int***型,四级指针就是int****型...............
只要你有兴趣,甚至可以依照这个规律写出一百级指针......
使用
面对二级指针时,解引用(*)一次得到的是一级指针
解引用(*)两次,就可以直接得到一级指针指向的数据
例如
#include <stdio.h>
int main()
{
int a = 0;
int* p1 = &a;
int** p2 = &p1;
printf("a的地址:%p,p1的地址:%p\n", &a, &p1);
printf("**p2的地址:%p,*p2的地址:%p", &**p2, &*p2);
return 0;
}
可以看到对二级指针p2解引用一次的地址是一级指针p1的地址
对二级指针p2解引用两次就能得到p1指向数据的地址
指针数组
含义
看名字就可以知道
指针数组就是一个存放指针变量的数组
与其他数组的不同之处在于里面存放的数据都为指针变量
作用
我们可以通过指针数组来模拟二维数组
假设一个二维数组a[3][3]存放的是{{1,2,3},{4,5,6},{7,8,9}}
我们可以通过一个指针数组来指向三个不同的一维数组实现模拟二维数组的作用
他们的关系可以用下图表示