什么是双指针
发布时间:2025-05-13 12:21:11 发布人:远客网络
一、什么是双指针
对于C语言的参数传递都是值传递,当传传递一个指针给函数的时,其实质上还是值传递,除非使用双指针。
在讲双指针之前,还是先讲讲关于C语言函数调用的本质。
函数调用操作包括从一块代码到另一块代码之间的双向数据传递和执行控制转移。数据传递通过函数参数和返回值来进行,包括局部变量的空间分配与回收,都是通过栈来实现的。绝大多数CPU上的程序实现使用栈来支持函数调用操作。栈被用来传递函数参数、存储返回信息、临时保存寄存器原有值以备恢复以及用来存储局部数据。当函数A调用函数B的时候,会把A的变量和参数压入到栈中,然后接着将B的变量和参数,局部变量压入到栈中。然后当A调用B是,B其实是在栈中取得A传递的参数和值,从而达到值传递的效果。
以一个交换2个数的值的函数调用为例。
那么,这段代码编译成汇编语言之后,除了会有代码段,数据段,堆栈,那么在调用的时候,会把main函数的参数变量压入main函数的栈帧,然后接着会压入swap函数的局部变量和参数。
<!--[if!vml]--><!--[endif]-->
<!--[if!vml]--><!--[endif]-->那么按照刚才上述理论,编译成汇编语言以后,这个图就是函数调用的时候内存形态。
有了上面的图和理论基础,再来讨论双重指针的问题。当定义的时候,只有一个*号的时候,我们叫它一级指针。**个星号的叫二级指针。
当我们使用一级指针的时候,我们试图使用下述错误代码来实现2个数交换
这种方式按照理论上来说,是想通过调用swap函数,在swap函数内部,实现将交换&a,&b,即交换a和b的地址来达到目的。这样绝对不可以。因为当把,a,b的地址传到swap函数之后,按照上述栈帧图的结构来看,最终swap函数值通过栈指针来实现的,当swap使用的时候,还是把a,b的地址复制到寄存器中才能运算。那么,大家也许就明白了,swap把a,b的地址复制到寄存器中,然后运算,相当于抱着a,b的副本跑了,然后去操作,这些所有针对,a,b副本的操作管main函数中的a,b什么事?当swap返回之后,这些寄存器或者是栈空间随着swap的然会而释放了,而main函数的a,b没发生任何变法。所以上述代码是错误的,无法实现你想要的功能。
当我们用二级指针来实现上述功能的时候有就可以达到效果。
这个时候,你会发现就能实现达到交换的目的。
这就是双指针神奇的功能,突破C语言传值的概念。那么,双指针是如何达到效果的呢?
当我们申明**a之后,其实双指针变量a其实已经存在了。那么在内存中的效果如下图
<!--[if!vml]--><!--[endif]-->
再来看这个图,p就是这里**a种的a.当我们申明**p之后,p就已经存在了。其实这个bridge也已经存在了,那么我们要做的就是bridge中放我们要操作的数的地址。也就是&incom;那么,其实这样操作*bridge就是操作&incom也就是&b啊,这个一级指针没什么区别啊。
请注意,对于一级指针,我们要操作的是就是b,那么按照汇编语言的规则,就要把b放到寄存器或者栈中去操作,我们相当于复制了一个副本去操作,等我们操作完了,返回函数,这些寄存器,栈等都释放了,main中什么也没发生。但是如果我们用双指针,二级指针就不一样了。我们操作的是bridge.我们只是机械的复制一个bridge的内容到寄存器或者到栈中,而没有实际的去复制imcom的内容,我们只是告诉bridge,你要指向一个叫incom的地址,也就是说,bridge的内容要是incom的地址,即&incom;所以,就达到目的了。所以,双指针让参数传递具有穿透力。
双指针主要用在但我们想一个A函数传递参数的时候,但是我们希望在A内部对参数做任何修改都能保存起来,那么就是用双指针吧。
我们在做链表的时候,我们肯定希望在用一个函数creatLink(...)函数来增加链表节点。那么我们可以有2种方法来实现
malloc...//为节点申请内存空间
//以后的任何操作,我们都要考虑,我们是否拿到的是链表头指针,到底哪个是链表波的头指针,我们是否要renturn下来返回链表头指针??等。。。。
这样做可以达到删除增加节点的目的,但是,在任何情况下,我们的操作都得死死地抓住头指针,也即是我们增加删除节点后,任何对链表长度的修改,我们都要将链表头指针返回,即 return head;所以,我们要通过这个函数最后获得头指针,抓住他,死死地抓住他,然后操作。
第二种方法:用双指针,也即是二级指针。
malloc...//为节点申请内存空间
//以后的任何操作,不管是删除还是插入,我们不需要考虑,我们是否已经return head了,不需要,我们在任何情况下,对链表的操作都只需要使用st来完成,因为,st就是链表的头指针,不变,因为在申明st的时候,已经为st分配一个地址空间,它是存在的,一直存在,直到main函数结束
原文地址
二、c语言中可以使用空指针的地址吗为什么例如
1、在C语言中,空指针是指指向空地址的指针,其值为NULL。空指针的地址是指空指针所指向的内存地址,也就是空地址。
2、在C语言中,可以使用空指针的地址,但通常不会主动使用它。空指针的地址通常由编译器自动分配,用于表示一个不存在的指针或者一个未初始化的指针。
3、使用空指针的地址可能会导致程序错误,因为它可能会被误解为指向一个有效的内存地址。如果程序尝试访问空指针的地址,可能会导致未定义的行为,例如崩溃或数据损坏。因此,在使用指针时,应该避免使用空指针的地址,而是使用有效的指针或者初始化的指针来避免潜在的问题。
4、以下是一个示例代码,演示了如何使用空指针的地址:
5、int*ptr= NULL;//定义一个空指针
6、printf("ptr的地址:%p\n", ptr);//打印空指针的地址
7、printf("ptr的值:%p\n",*ptr);//打印空指针所指向的内存地址
8、在这个示例中,我们定义了一个空指针ptr,并使用printf函数打印了它的地址和所指向的内存地址。可以看到,这两个值是相等的,因为空指针没有指向任何有效的内存地址。需要注意的是,这个示例只是演示了如何使用空指针的地址,实际应用中应该避免使用空指针的地址,以避免潜在的问题。
三、c语言中指针到底有几种类型啊
1、枚举和指针类型都不是基本数据类型C语言有五种基本数据类型:字符、整型、单精度实型、双精度实型和空类型。
2、尽管这几种类型数据的长度和范围随处理器的类型和C语言编译程序的实现而异,但以bit为例,整数与CPU字长相等,一个字符通常为一个字节,浮点值的确切格式则根据实现而定C语言还提供了几种聚合类型(aggregate types)。
3、包括数组、指针、结构、共用体(联合)、位域和枚举除v o i d类型外,基本类型的前面可以有各种修饰符。
4、修饰符用来改变基本类型的意义,以便更准确地适应各种情况的需求。
5、C语言普适性最强的一种计算机程序编辑语言,它不仅可以发挥出高级编程语言的功用,还具有汇编语言的优点,因此相对于其它编程语言,它具有自己独特的特点。具体体现在以下三个方面:
6、其一,广泛性。C语言的运算范围的大小直接决定了其优劣性。C语言中包含了34种运算符,因此运算范围要超出许多其它语言,此外其运算结果的表达形式也十分丰富。
7、此外,C语言包含了字符型、指针型等多种数据结构形式,因此,更为庞大的数据结构运算它也可以应付。
8、其二,简洁性。9类控制语句和32个KEYWORDS是C语言所具有的基础特性,使得其在计算机应用程序编写中具有广泛的适用性,不仅可以适用广大编程人员的操作,提高其工作效率,同时还能够支持高级编程,避免了语言切换的繁琐。
9、其三,结构完善。C语言是一种结构化语言,它可以通过组建模块单位的形式实现模块化的应用程序,在系统描述方面具有显著优势,同时这一特性也使得它能够适应多种不同的编程要求,且执行效率高。