详解C语言二级指针

本文深入探讨了C语言中的二级指针,解释了如何在函数内部改变一级指针的值,通过实例展示了如何使用二级指针来修改变量的存储位置。文章还提到了二级指针在链表操作中的应用,特别是在向链表末尾添加元素时的作用。此外,还通过代码示例说明了传值调用与传指针调用的区别。
摘要由CSDN通过智能技术生成

详解C语言二级指针

众所周知,指针实际上是一个,类比int类型,在处理指针的一些操作时我们就会遇到一些问题。比如下面这个知名的程序:

#include<stdlib.h>
#include<stdio.h>

void change(int a) { a = 2021;}

int main() {
	int a = -1;
	change(a);
	printf("%d\n",a);
}

运行结果是-1而不是2021。原因在于函数通过传值方式进行传参时,会先在另外一个地方(空间)拷贝该值供函数使用。例如在上一个例子中,在main函数中将a传给函数change时,会重新开辟一个空间存储a的值,在函数体内直接操作的都只是一个拷贝(复印件)而不是main函数中的a(原件)。我们可以写下面这么一个简单的程序进行验证:

#include<stdlib.h>
#include<stdio.h>

void change(int a) { 
	printf("change函数中a的地址:%p\n",&a);
	a = 2021;
}

int main() {
	int a = -1;
	printf("main函数中a的地址:%p\n",&a);
	change(a);
	printf("%d\n",a);
}

在我的PC上的运行结果如下所示:

main函数中a的地址:0x7ffee2f3d9cc
change函数中a的地址:0x7ffee2f3d9ac
-1

那么我们如何在change函数中改变main函数中a的值呢?传指针!!传值的时候我在函数里面摸不到你,但是通过传指针我可以通过指针(也就是一级指针,可以理解成只有一个*)找到其存储位置从而对其更改:

#include<stdlib.h>
#include<stdio.h>

void change(int *a) { *a = 2021;}

int main() {
	int a = -1;
	change(&a);
	printf("%d\n",a);
}

这样子运行结果就是2021了。

到此,总结一下,原值在函数内需要借助一级指针进行更改,前面提到指针实际上就是一个数,所以我们传一级指针本身给函数我们只能修改这个指针指向的空间的值,而不能修改一级指针本身。 验证代码如下所示:

#include<stdlib.h>
#include<stdio.h>

void change(int *a, int *b) 
{
	a = b;
}
int main() {
	int a = 1921, b = 2021;
	change(&a, &b);
	printf("%d\n",a);
}

运行结果是1921而不是2021。可以看到main好书中的指针a 并没有更改成指针b,原因在于传指针给函数时同样会对指针进行拷贝使用

那么如何在函数内更改一级指针呢? 答案是二级指针。

上面代码改成这样就可以了:

#include<stdlib.h>
#include<stdio.h>

void change(int **a, int **b) 
{
	*a = *b; //更改一级指针
}
int main() {
	int a = 1921, b = 2021;
	int *c = &a, *d = &b;
	change(&c, &d);
	printf("%d\n",*c);
}

运行结果是2021,一级指针c成功改成了指针d。这也就是二级指针的用处,举个特别实际的例子:链表,向链表末尾添加元素的代码如下所示:

#include<stdlib.h>
#include<stdio.h>

typedef struct node{
	int value;
	struct node *next;
}link;

void insert(link **head, int v) {  //使用二级指针,为了方便修改头节点指针
	if(*head == NULL) {
		*head = (link *)malloc(sizeof(link));
		(*head) -> value = v;
		(*head) -> next = NULL;
	}else{
		link *cur = *head;
		while(cur -> next != NULL) cur = cur -> next;
		cur -> next = (link*)malloc(sizeof(link));
		cur -> next -> value = v;
		cur -> next -> next = NULL;
	}
}

void print(link *head) {  //输出链表内容
	while(head != NULL) {
		printf("%d ",head -> value);
		head = head -> next;
	}
	printf("\n");
}

int main() {
	link *head = NULL;
	insert(&head, 1921);
	insert(&head, 2021);
	print(head);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值