title: 巧用二级指针
date: 2024-09-14 20:52:50
description: two level pointer
tags:
skaiuijing
但是,真正理解指针作为变量的本质,才能真正理解指针。
而二级指针,代表指向指针的指针。
以下是示例:(开发环境的编译器为32位,所以指针为4个字节)
#include<stdio.h>
#include<malloc.h>
int main()
{
int a =1;
int *pa = &a;
int **ppa = &(pa);
int ***pppa = &(ppa);
//printf("pppa-value:%d",(int)(&(&(&a)))); //请思考这样做是否可行?
printf("pa-value:%d\n",(int)&a);
printf("ppa-value:%d\n",(int)(&(pa)));
printf("pppa-value:%d\n",(int)(&(ppa)));
}
为了直观理解,多级指针的内存布局如下(模型更接近汇编):
变量 | 存储的值 | 地址 |
---|---|---|
int ***pppa | 6422016 | *** |
int **ppa | 6422024 | 6422016 |
int *pa | 6422036 | 6422024 |
int a | 1 | 6422036 |
其实int a和int*a没有本质区别,它们只不过都是变量而已
这么一看,(int)(&(&(&a)))这个操作肯定是不行的,认为这样是可行的朋友,一定是把多级指针当成了这样:
参考上文的模型,这是不合理的。
真实的情况是这样的:
所以说,(int)(&(&(&a)))中,只有&a是成立的,&(&a)完全是错误且荒谬的。
现在我们该面对多级指针了。
经常有人看见多级指针就害怕,其实多级指针并不神奇。
如果我们寻求ai或者搜索引擎,渴望得到多级指针的精髓,以二级指针为例,我们得到的答案往往是这样的:
二级指针最常见的用法就是修改一级指针。
示例:
#include<stdio.h>
void sparrowfly()
{
printf("sparrowfly!\n");
}
void eaglefly()
{
printf("eaglefly!\n");
}
typedef void (*impletation)();
struct bird *table[] = {
eaglefly,
sparrowfly
};
void change(struct function **x,int id)
{
*x = table[id];
}
int main()
{
impletation impll;
struct function **twopinter = &impll;
change(twopinter, 1);
impll();
return 0;
}
使用二级指针,这样就是传址调用,而不是传值调用了。
笔者也可以自己实验一下:
void change(struct function *x,int id)
{
x = table[id];
}
int main()
{
impletation impll;
struct function **twopinter = &impll;
impll = eaglefly;
change(impll, 1);
impll();
return 0;
}
传址调用对于多级指针也是成立的,毕竟笔者前面已经说过,指针的本质是变量。
多级指针还有一个好处:增加程序可扩展性和解耦合。
#include<stdio.h>
#include<malloc.h>
typedef void (*fly)(struct bird **self);
struct bird{
fly common;
};
struct sparrow{
struct bird *interface;
char name;
};
struct eagle{
struct bird *interface;
char name;
};
void sparrowfly()
{
printf("sparrowfly!\n");
}
void eaglefly()
{
printf("eaglefly!\n");
}
struct bird **fly_table[] = {
(struct bird **)&(struct sparrow) {
.interface = &(struct bird) {.common = sparrowfly},
.name = 's'
},
(struct bird **)&(struct eagle){
.interface = &(struct bird){.common = eaglefly},
.name = 'e'
}
};
void polymorphism(int opt)
{
struct bird **p = fly_table[opt];
(*p)->common(p);
}
int main()
{
polymorphism(0);
return 0;
}
这一段程序虽然self指针也可以被一级指针代替,但是当我们在main函数中修改一些局部指针变量时,二级指针的扩展性就体现出来了:
#include<stdio.h>
#include<malloc.h>
typedef void (*fly)(struct bird **self);
struct bird{
fly common;
};
struct sparrow{
struct bird *interface;
char name;
};
struct eagle{
struct bird *interface;
char name;
};
void sparrowfly()
{
printf("sparrowfly!\n");
}
void eaglefly()
{
printf("eaglefly!\n");
}
struct bird **fly_table[] = {
(struct bird **)&(struct sparrow) {
.interface = &(struct bird) {.common = sparrowfly},
.name = 's'
},
(struct bird **)&(struct eagle){
.interface = &(struct bird){.common = eaglefly},
.name = 'e'
}
};
void implement(struct bird **p)
{
(*p)->common(p);
}
void polymorphism(int opt)
{
struct bird **p = fly_table[opt];
(*p)->common(p);
}
struct bird *table[] = {
eaglefly,
sparrowfly
};
void change(struct bird **self,int id)
{
(*self)->common = table[id] ;
}
int main()
{
struct sparrow sparrow1;
struct bird bird1;
sparrow1.interface = &bird1;
struct bird **Ainterface ;
Ainterface = malloc(sizeof(int));
*Ainterface = sparrow1.interface;
change(Ainterface,0);
implement(Ainterface);
polymorphism(0);
return 0;
}
当然,指针也并不是越多级就越好,我们也看到了,指针的本质仍然是变量,只是对存储的值有一定要求而已。过多级数的指针并不会带来更好的程序优化,相反,可能使程序性能、可读性、可维护性变差。