指针即地址,不管是二级指针还是一级指针,指针变量都表示一个地址。
一级指针是指向地址的变量,二级指针是指向一级指针地址的变量。(定义指针变量时要开辟一块内存,用于存贮指针变量的值及该指针指向的地址,同时,开辟的这块内存本身也有地址,二级指针可以指向这块地址)
win32操作系统下,一个指针类型占4字节,64位操作系统占8字节。(字节大小涉及二级指针偏移量)
int a = 10;
int *p = &a;//*p=a=10,p=&a
int **t = &p;//t=&p,*t=p=&a,**t=*p=*(&a)=10
‘*’ 解引用符号的操作数必须是数组,一级指针可以解引用一次,二级指针解引用一次后相当于一级指针,可以再解引用一次,所以二级指针可以解引用两次。
数组名相当于数组首元素地址,数组名本质是一个指针常量,也可以解引用;
关于指针偏移量:
一级指针偏移量与指针的类型有关,整形偏移4字节,字符型偏移1字节
int arr[10] = {0};
int *p = arr;
*p = arr[0];
p++;//指针+1,偏移4字节
*p = arr[1];//一级指针偏移量大小即指针数据类型的字节数
char s[10];
char *ptr = s;
*ptr++=s[0];
*ptr=s[1];//原理同上
二级指针偏移量为8字节(win32/4字节,win64/8字节),因为二级指针指向一级指针地址,而指针类型占8字节。
int arr[6] = {1,2,3,4,5,6};
int **p = arr; //即p=arr=&arr[0]
*p++ = arr[0] = 1; //*p=*(arr)=*(&arr[0])=1
*p = arr[2] = 3; //二级指针+1偏移8字节,一个整型占4字节
综述,指针偏移量即指向数据类型的字节大小。
二级指针的作用:
作为函数形参,传入一级指针地址
int a = 10;
int b = 100;//定义全局变量
void zhizhen(int **p1)
{
*p1=&b;
}
int main()
{
int *p2=&a//初始化,规避野指针
//此时*p2=10
zhizhen(&p2);//将一级指针的地址传给二级指针,即函数内**p1=&p2
//函数内*p1=*(&p2)=p2=&b,*p2=100
指向指针数组(区别数组指针)
int a[3]={1,2,3};
int b[3]={4,5,6};
int c[3]={7,8,9};
int* arr[3]={a,b,c};//创建一个指针数组
//数组名arr,相当于一个指针常量,数组内元素数据类型为int*指针类型,因为数组元素abc都是数组名,都小于一个指针常量
int **p=arr;
//p此时指向指针数组arr首地址
**p=1 //**p=*(*p)=*(*(arr即&arr[0]))=*(a)=*(&a[0])=a[0]=1
**(p+1)=4
/*二级指针偏移量为8(见上文),而指针数组arr内存放的元素都是指针常量,每个元素相隔地址也是8字节,正好等于偏移量,所以**p=*(*(&arr[1]))=*(b)=*(&b[0])=4
指针数组要区别于数组指针:*/
int (*s)[3]={11,12,13};//数组指针是一个指向数组的指针,数组内元素为int
/*
如何区别数组指针和指针数组呢?
优先级()>[]>*
int *p[],p先与[]结合创建一个数组,其内元素类型为int*
int (*p)[],()>[],括号内p先与*结合定义一个指针,这个指针指向数组,然后(*p)与[]结合创建数组,元素类型为int
*/
最后,代码如下
理解以上内容,上图基本就能看得明白,不过图内的一些输出我也没有搞明白(如最后一行输出)