一级指针和二级指针的区别

简介: 一级指针和二级指针的区别

本文详细解析了一级指针(如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 *nodehashnode_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 *的地址组成

推荐学习https://xxetb.xetslk.com/s/p5Ibb

目录
相关文章
|
17天前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
24天前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
5月前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
71 1
|
4月前
|
存储
头指针和头结点的区别
头指针和头结点的区别
141 1
|
5月前
|
C语言
C语言--指针数组和数组指针的区别
C语言--指针数组和数组指针的区别
|
6月前
|
存储
结构体和结构体指针的区别
结构体和结构体指针的区别
168 1
|
6月前
|
存储
引用和指针的区别
引用和指针的区别
44 3
|
5月前
|
C++
【C++系列】指针对象和对象指针的区别
这段内容介绍了C++中`ListNode`对象和指针的两种使用方式以及它们的区别。首先,`ListNode dummy(0); ListNode* cur = &dummy;创建了一个`ListNode`对象`dummy`在栈上,`cur`是`dummy`的地址。而`ListNode* dummy = new ListNode(0); ListNode* cur = dummy;`则在堆上分配了一个`ListNode`,`dummy`和`cur`都是指向该对象的指针。使用`&dummy`作为虚拟头节点简化链表操作,避免特殊处理。栈分配内存自动管理但生命周期受限,堆分配内存需手动释放且速度较慢。
|
5月前
|
存储 C语言
C语言数组指针和指针数组的区别及使用方法
C语言数组指针和指针数组的区别及使用方法
87 0