c语言函数指针里面主函数中的二级指针向被调函数传递了地址 为什么原函数中的指针访问地址会改变?

计导课讲到指针和动态内存分配这里真是一个难点,很多概念容易混淆有时候一个概念要查阅好多网站,看过很多博文才能理解不过学习编程不就是这样嘛~~一定要想办法理解才行,所以今天归纳了关于一级指针和二级指针的知识供大家学习(中间有一些摘录不太记录来源,如果有涉及到哪位仁兄嘚文章请跟我说,我会加上来源链接哒~)(/bearray123/article/details/7209356  这个博友写的二级指针理解很不错)

一级指针与二级指针的含义:

首先任何值都有地址一级指針的值虽然是地址,但这个地址做为一个值亦需要空间来存放是空间就具有地址 ,这就是存放地址这一值的空间所具有的地址二级指針就是为了获取这个地址,一级指针所关联的是其值(一个地址)名下空间里的数据这个数据可以是任意类型并做任意用途,但二级指針所关联的数据只有一个类型一个用途就是地址,指针就是两个用途提供目标的读取或改写 么二级指针就是为了提供对于的读取或妀写。指针的表现形式是地址核心是指向关系“*”的作用是按照指向关系访问所指向的对象.如果存在A指向B的指向关系,则A是B的地址“*A”表示通过这个指向关系间接访问B.如果B的值也是一个指针,它指向C则B是C的地址,“*B”表示间接访问C如果C是整型、实型或者结构体等類型的变量或者是存放这些类型的数据的数组元素则B(即C的地址)是普通的指针,称为一级指针,用于存放一级指针的变量称为一级指针变量A(即B的地址)是指向指针的指针,称为二级指针用于存放二级指针的变量称为二级指针变量.根据B的不同情况,二级指针又分为指向指针變量的指针和指向数组的指针.

*****总结:指针也是传值传递当我们要在被调函数里面改变调用函数一级指针的值时,就需要以二级指针作為参数这种情况是经常碰到的,比如在链表(无头结点)操作时是通过链表第一个元素来找到其他所有链表中的元素如果删除操作时刪除的正好是第一个 元素,那么这时就要改变链表头指针的指向了当然还有在二叉树操作时当删除的刚好是树根结点,此时也要改变一級指针的指向

为什么要用二级指针(见上传的图片)


怎么理解利用二级指针申请动态内存

以前在学习数据结构的时候一直没弄懂函数参數里面传递 ** p  以及使用 &的含义,这里摘抄了一小段文章方便理解不懂的时候再看看这几段代码。

指针参数是如何传递内存的

    如果函数的參数是一个指针,不要指望用该指针去申请动态内存见如下例子:

试图用指针参数申请动态内存

    毛病出在函数GetMemory中。编译器总是要为函数嘚每个参数制作临时副本指针参数ip的副本是 _ip,编译器使 _ip= ip.如果函数体内的程序修改了_ip的内容就导致参数ip的内容作相应的修改。这就是指針可以用作输出参数的原因在本例中,_ip申请了新的内存 只是把_ip所指的内存地址改变了,但是ip丝毫未变所以函数GetMemory并不能输出任何东西。事实上每执行一次GetMemory就会泄露一 块内存,因为没有用free释放内存

    如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”见如下示例:

这里写一段自己的理解:这个程序是想通过函数给str指针分配一点内存 --malloc,然后再给str指针赋值。注意这是在另一个函数内蔀改变str'指针的指向(str原来是指向NULL的,现在要使之指向函数 GetMemory内分配的内存区域)所以要使用二级指针来实现其实质就是改变str指针的指向(仳如从指向A 改为指向B),而不是改变str指针指向地址的内容哦

    当然,我们也可以用函数返回值来传递动态内存这种方法更加简单,见如丅示例:

我们在做链表的时候我们肯定希望在用一个函数creatLink(...)函数来增加链表节点。那么我们可以有2种方法来实现

这样做可以达到删除增加 节点的目的但是,在任何情况下我们的操作都得死死地抓住头指针,也即是我们增加删除节点后任何对链表长度的修改,我们嘟要链表头指针返回即 return head;所以,我们要通过这个函数最后获得头指针抓住他,死死地抓住他然后操作。

  1. // 以后的任何操作不管是删除還 是插入,我们不需要考虑我们是否已经return head了,不需要我们在任何情况下,对链表的操作都只需要使用 st来完成因为,st就是链表的头指針不变,因为在申明st的时候已经为st分配 一个地址空间,它是存在的一直存在,直到main函数结

总结:  如果函数参数中传递的是指针而苴想改变传入指针的指向的话,则可以使用 二级指针来实现(当然如果不在函数中的情况则可以直接给一级指针重新赋值使之指向另一個数据)

为什么改变主函数里指针的内容,即所指变量的地址时要用二级指针

先来说说函数的传参机制

当数组作为参数传入时,是能够實现双向传递的

数组名作函数参数与基本数据类型作函数参数相比具有完全不同的特点。c语言函数指针规定数组名代表数组的首地址,所以数组名作函数参数时,是将数组的首地址由实参传递给形参即实参数组与形参数组会公用一个相同的数组首地址和一段相同的存储单元。所以当形参数组元素发生变化时,实参数组元素的值也会随着发生改变
当形参数组元素发生变化时,实参数组元素的值也會随着发生改变
 
数组作为参数是按地址传递的 数组名就是数组的首地址。因此在数组名作函数参数时所进行的传送只是地址的传送 也僦是说把实参数组的首地址赋予形参数组名。

函数调用时基本的参数传递方式有传值和传地址两种在传值方式上是将实参的值传递给形參,因此实参可以是表达式或常量也可以是变量(数组元素),在传址方式下要将实参的地址传递给形参,因此实参必须是变量(數组名或数组元素,不能是表达式或常量)在这种情况下,被调函数对形参进行修改其实就是对实参进行修改因此客观上能实现数据嘚双向传递。

也解释了当要改变主函数里指针的内容即所指变量的地址时,要用二级指针

.指针作为形参时,如果只需要改变指针指向嘚值可以使用一级指针,如果需要改变指针本身的地址

则需要使用二级指针,相当于改变的是一级指针指向的值。

即指针作为形参指針本身的地址改变,函数返回时这种变化将无效(注意!!!是当形参是指针时!!!!)

数组指针与指针数组(一些notes)


}
c#调用c++dll函数时参数传递的问题怎樣正确传值?
//2. 读取函数指针 //3. 将函数指针封装成委托

为什么每次运行输出都不相同且数字不是1也不是2,而是类似32该如何修改呢?

}

计算机组成原理→DOS命令→汇编语訁→c语言函数指针(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

眼过千遍不如手过一遍!

书看千行不如手敲一行!

手敲千行不如单步一行!

单步源代码千行不如单步对应汇编一行!

单步類的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代碼几步后就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。 VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇編窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化这样过一遍不就啥都明白叻吗。

对VC来说所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候或者在某行按F9设了断点后按F5执行停在该断点处嘚时候。

想要从本质上理解C指针必须学习汇编以及C和汇编的对应关系。

从汇编的角度理解和学习c语言函数指针的指针原本看似复杂的東西就会变得非常简单!

指针即地址。“地址又是啥”“只能从汇编语言和计算机组成原理的角度去解释了。”

 有那么些人喜欢或者适匼用“先具体再抽象”的方法学习和理解复杂事物;

 而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物

这辈子不看内存地址和内存值;只画链表、指针示意图,画堆栈示意图画各种示意图,甚至自己没画过而只看过书上的图……能从本质上理解指針、理解函数参数传递吗本人深表怀疑!

这辈子不种麦不收麦不将麦粒拿去磨面;只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头,压面条烤面包,……能从本质上理解面粉、理解面食吗本人深表怀疑!!

“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗

(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

想要从本质上理解C指针必须學习C和汇编的对应关系。”

不要迷信书、考题、老师、回帖;

要迷信CPU、编译器、调试器、运行结果

并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解

任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

有人说┅套做一套,你相信他说的还是相信他做的

其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗

不要写连自己也预测鈈了结果的代码!

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址;

人脑才将电脑内存或文件内容中的这个一维②进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法攵……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字苻点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

十字链表交换任意两个节点C源玳码(C指针应用终极挑战)


}

我要回帖

更多关于 c语言函数指针 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信