本文详细解析了一级指针(如char*p和char[]c)以及二级指针(如char**pp)在C语言中的区别,通过实例展示了它们如何存储地址和访问数据。还介绍了如何在哈希表结构中使用二级指针来管理节点。
摘要由CSDN通过智能技术生成
这是一个一级指针:
char *p;
这是一个二级指针:
char **pp;
有什么区别呢?
一、一级指针
p是一个指向char类型变量的变量,说起来有点绕口,简单来说,p可以保存一个变量的地址
char c = 'a'; char *p = &c; printf("%p", p);
此时可以显示p的值,是一个十六进制数,表示变量c的地址
同时,一级指针可以用来声明一个数组:
char c[]; char *p;
第一行声明的c也是一个指针,指向该数组的第一个元素,保存着数组的首地址,也就是第一个元素的地址
实际上声明一个数组就是声明了一个指针,这个指针保存着该数组空间的首地址
char *p = "abc";
这行代码将字符串常量"abc"的首地址也就是字符’a’的地址赋给了p,所以此时的p并不是指向一个字符串,而是字符串的首地址,通过首地址p可以访问到该字符串的全部字节空间,所以才说p指向字符串,而实际上并没有
数组也是如此:
char c[] = "abcd"; char *p = &c;
由于c是该字符数组的首地址,p也就保存着该字符数组的首地址,其实字符串就是一个以\0为结尾的字符数组
二、二级指针
"二级指针是一个指向指针的指针"或许很难理解,强行解释一下:二级指针是一个保存着一个一级指针的地址的变量。或许很难理解,但没关系,我们慢慢了解:
char *p = "abcd"; char **pp = &p;
p是一个一级指针,保存着一个字符数组的首地址,即字符’a’的地址
pp是一个二级指针,保存着p这个变量的地址
好像二级指针并没有什么作用啊,看上去是的,思考一下一级指针:
char *p = 'a';
此时这个一级指针p似乎也没有什么用,p保存着字符’a’的地址,我们不能做任何事,但:
char *p = "abc";
此时p还是保存着字符’a’的地址,但是!!
while(p){ printf("%c", *p); p++; }
可以通过p打印出 abc !
这就是一级指针最简单的作用了,那么二级指针呢?
char *p = "abcd"; char **pp = &p;
这个例子中pp保存着一个p的地址,可以通过p访问到字符串"abcd",那么pp++呢?这里是未定义的,所以只要pp保存的地址也是连续的(且可访问),那么就可以通过pp访问到多个字符串,类比p可以访问到一个字符串,是不是豁然开朗了!
实现:
char *x[] = {"abc", "def", "qwe"}; char **pp = x;
这里的x是一个二级指针,它保存着一个一级指针的地址,这个一级指针保存的地址是"abc"的首地址
x++后,x保存的是另一个地址,这个地址是另一个一级指针的地址,这个一级指针保存的地址是"def"的首地址
这两句话一定要理解!如果不理解,做一个不正确的比喻:
x是一个数组,数组的每个位置保存着一个指针,每个指针指向一个字符串如"abc",这样,x就保存着多个字符串了。
为了便于理解才多写了一个x,实际上可以这么写:
char **pp = {"abc", "def", "qwe"};
这样写是不是根本无法理解,说实话这样写我也不能理解
进阶篇
这里我们改变指针的类型:结构体
typedef struct hashnode_s { // hash节点 char *key; char *value; struct hashnode_s *next; } hashnode_t; typedef struct hashtable_s { // hash表 hashnode_t **nodes; // hashnode_t * 类型的 *nodes, 也就是存放着hashnode_t类型指针的数组nodes int max_slots; int count; } hashtable_t;
这是一个哈希表的结构,包括哈希节点和哈希表
这里通过哈希节点说明两级指针的使用:hashnode_t *node
和hashnode_t **nodes
一级指针
hashnode_t *node = (hashnode_t*)malloc(sizeof(hashnode_t)); // 为哈希节点分配空间
这是对一级指针的初始化,用一级指针指向一块空间,保存该空间的首地址,是不是和char类型的一级指针如出一辙
由于node是指向hashnode_t结构体对象的指针,它保存的是一个hashnode_t对象的地址,malloc的大小即为结构体的大小
二级指针
// 为哈希表结构分配空间 由于nodes是二维指针,指向一个指针, // 分配一段连续的空间,空间的单位是一个指针大小,nodes++时每次递增一个指针的地址大小 // hashnode_t **nodes可以访问hashnode_t* 对象, 而 hashnode_t *nodes可以访问hashnode_t 对象 hashnode_t **nodes = (hashnode_t**)kvstore_malloc(sizeof(hashnode_t*) * 10);
这是对二级指针nodes的初始化,由于nodes是指向hashnode_t指针的指针,它保存的是一个指针的地址,这个指针就是一级指针node,所以malloc大小是sizeof(hashnode_t *) * 10,含义是保存的地址的单位是一个指针的大小,数量是10,也就是说nodes保存着一段连续空间的首地址,这一段连续空间的地址由10个一级指针hashnode_t *的地址组成