C语言多级指针含义归纳

前言

今天在实习二叉排序树的结点删除时,用到了三级指针。
一下子有些困惑了。

一番思考,才觉得对指针的理解更透彻了。

条理地总结一下,从多个角度来分析,可以让思路更清晰。

不同角度的含义单独来看不复杂,但是组合在一起就容易使我们陷入困惑。

理解了各个角度下的含义,才能明白什么时候、为什么要用(多级)指针。

前置知识——C语言传参/返回规则

C语言中,传递参数,实际传递过去的是参数的副本,而非本体;返回值时,返回的实际是值的副本,而非本体。

参数传递,本质上只有按值传递。按址传递只是象征意义上的,或者说根本没有。

下面的代码可以证明这一点:

#include 

int func (int a)
{
	printf ("func: a: %p\n", &a);
	int b;
	printf ("func: b: %p\n", &b);
	return b;
}

int main (void)
{
	int a;
	printf ("main: a: %p\n", &a);
	int b = func (a);
	printf ("main: b: %p\n", &b);
}

输出结果为:

main: a: 0x7ffdea4df35c
func: a: 0x7ffdea4df32c
func: b: 0x7ffdea4df33c
main: b: 0x7ffdea4df358

每个变量的内存地址在传参前后、返回前后都不一样,说明它们不是在同一片内存,只是值相同。

1. 通用的多级指针含义

从传参的角度来讲,只有一种指针:一级指针。
因为所有的指针都是为了保存本体,而非副本。

一级指针是为了得到值本体,二级指针为了得到一级指针本体,依此类推。

总而言之:得到本体。

2. 数组中多级指针的含义

这个没什么好说的,只是为了完整性。

一维数组是一级指针,二维数组是二级指针,三维数组是三级指针……

这样下去就是是一万级指针也好理解。

3. 数据结构中多级指针的含义(重要)

指针的用途很多,容易困惑我们的多是数据结构中的多级指针,在此给出它们的含义:

从控制的角度来说,

  • 一级指针的意义,是控制内存。
  • 二级指针的意义,是对结构和关系的控制

3.1 内存控制

比如,Node * ptr = malloc(sizeof(Node));

这里的一级指针ptr拥有了对内存空间的绝对控制权。

3.2 结构与关系的控制

比如,有一个结构体:

typedef struct Node{
  struct Node * left;
  struct Node * right;  
}Node;

然后,你构建了一棵树:

Node * tree = create_tree();

如果你想改变树中某个结点的值,如前面所说,它的意义就是内存控制,只需一级指针即可,函数的原型就是>这样:

void modify_tree(Node *tree);
//或者你喜欢另一个名字:
void modify_some_node(Node *node);

然而,如果你想要改变树的结构/关系——结构/关系的含义我们可以将它理解为指针(当然,也可以用索引来表示,比如用数组实现一颗树),那就意味着你想要改变一个指针,这样在函数参数传递时,由于参数会以副本的形式传递,我们必须使用指针的指针,也就是二级指针。

总而言之:

改变值,即是控制内存,使用一级指针即可。
改变结构,即是改变指针,需要用二级指针。

在写代码时想好你到底要改变什么、在改变什么,就不会困惑。

4. 内存拷贝中的多级指针含义

64位机的指针的大小是8字节,32位机的大小是4字节。

通过传递指针来访问内存,就可以不用直接传递值,减少拷贝量。

比如有个结构体:

struct LargeType{
    
int _1;
int _2;
...
int _999999;
}

所以指针传参意味着可以减少拷贝。当然,基本类型占用字节不比指针多,这样就没必要传指针,除非你想访问本体而非副本。

在数据结构中,一级指针只对所指内存有绝对控制权,二级指针对结构(包括内存)有控制权。

部分改变结构的操作,一级指针和二级指针都可完成,但是一级指针需要深拷贝,二级指针则可以浅拷贝。

比如将某个结点替换为它的子结点,一级指针,需要将子结点的内存复制到父结点,而二级指针只需将父结点指针赋值为子结点即可:

一级指针:

typedef struct Node{
    struct Node *child
}Node;

void repalce_father_to_child(Node* tree)
{
    *tree = *tree->child;//深拷贝,拷贝结构体
}

二级指针:

typedef struct Node{
    struct Node *child
}Node;

void repalce_father_to_child(Node** ptree)
{
    *ptree = tree->child;//浅拷贝,只拷贝指针 
}

你可能感兴趣的:(数据结构,C语言,c语言,开发语言)