关于函数传一级指针与二级指针的问题

奋斗小青年 2011-08-05 11:29:03
网上看很多资料,谈到值传递与引用传递。认为指针传递是值传递,传进来的是实参的副本。
比如一个这样的函数 void passParamType(char * p)
{
// p = &全局变量;
//*p = 'a';
}

void passParam2Type(char ** p)
{
//p = &另外的全局变量;
//*p = "mgh";
}
前面两个方法主要涉及到的一级指针与二级指针改变地址与所指向的内容的问题。
当函数传实参进来,比如第一个函数 就好像 p = array; 第二个也一样,其中array是个字符数组。
下面来说说我的想法。 对于两个函数当p = &全局变量,此时很多资料都是说此时操作的是实参的副本对实参没影响,这里我就有点迷糊了,这里干嘛非得扯上实参的副本,还是编译器机制就是这样(PS:编译器机制我不知道)p = &全局变量 这里是对形参重新给予了新的地址,对实参当然没影响。*p 这里倒好理解,形参p指向的实参的地址,*p当然就是实参的内容,因此就可以改变。 求各位麻烦指教下,小弟在此学习了。还望大家多指出我的错误所在。
...全文
502 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
Xomic 2011-08-05
  • 打赏
  • 举报
回复
还是传值,传址,引用的三种调用啊!

传值:实参给形参传值过后,他们再也没有任何瓜葛!

传址:也就是把实参的地址赋给形参(指针),从而间接改变实参的值!

引用:形参是实参的引用,这就是直接操作改变实参的值!

我是这样理解的,如有不妥之处还请高手指点。。。
jernymy 2011-08-05
  • 打赏
  • 举报
回复


void Tst(int *pnData) // pnData为形参,pnData指向nA的地址
{
*pnData = 50;
}

int main(void)
{
int nA = 10;

Tst(&nA); // nA 为实参
return 0;
}
hua_yang 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 hua_yang 的回复:]
实参和形参的概念再理解一下

形参重新给予了新的地址,//我个人理解形参是函数定义时的一个概念,形式上的参数,代表这个参数的类型。

实际运行时,传入一个指针假如是p,系统会定义个新的指针指向p1,然后将p1=p,函数里通过p1来操作

这就是为什么叫副本
[/Quote]

笔误,应该是:系统会定义个新的指针p1

形参和实参只是概念

实际运行中都是数据的传递,指针的拷贝,指针的副本,叫什么都行

理解内部是怎么工作的就行
赵4老师 2011-08-05
  • 打赏
  • 举报
回复
无汇编,无真相!

VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

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

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
那资料上面说的副本难道就是形参?如果是这样,那我所提的问题,就可以攻破了。 期待各位发言
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
9楼有点靠近我需要的答案了。再期待,欢迎各位踊跃发言,小弟虚心学习。
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
等待我期望的答案。
hua_yang 2011-08-05
  • 打赏
  • 举报
回复
实参和形参的概念再理解一下

形参重新给予了新的地址,//我个人理解形参是函数定义时的一个概念,形式上的参数,代表这个参数的类型。

实际运行时,传入一个指针假如是p,系统会定义个新的指针指向p1,然后将p1=p,函数里通过p1来操作

这就是为什么叫副本
xiaoguangzaia 2011-08-05
  • 打赏
  • 举报
回复
你理解的对的
这个副本是说函数里面的那个参数又重新分配了一块内存用来存储这个指针,只是这个内存里面存放的内容
和实参内存里存放的内容一样(指针的话就是两个指针都指向同一块内存)。
普通的值传递和指针传递都是这样的
但是引用的时候就不会从新分配一块内存了,只是给实参其个别名
johnny_83 2011-08-05
  • 打赏
  • 举报
回复
其实,资料上说的实参的副本这么样得来的。其实指针就是一个变量,这个变量存放另一个变量的地址,不管是普通指针还是二重指针都是一样的这种理解。在函数传参时,采用的是值拷贝,指标变量的值拷贝,还是指针变量,指针变量里的值没有改变,所以它指向的地址也没有改变。引用指针里的地址所在变量,当然是同实参是同一个变量了。修改其值,就是修改实参的值。理解了吗?小弟
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
现在我这里谈论的是为啥有的资料为啥是说传递的副本问题,请各位看清我说的话。其实我个人感觉副本这词明显是多余,不知大家有啥看法没,多指点迷津啊 高手们
shishuiruoshang 2011-08-05
  • 打赏
  • 举报
回复
指针传递传副本是说传的是指针所引用内存的副本,就指针值本身而言当然是值传递了
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 wanyuan19890515 的回复:]
网上看很多资料,谈到值传递与引用传递。认为指针传递是值传递,传进来的是实参的副本。
比如一个这样的函数 void passParamType(char * p)
{
// p = &全局变量;
//*p = 'a';
}

void passParam2Type(char ** p)
{
//p = &另外的全局变量;
/……
[/Quote]

这里 p与*p只执行一个 不是按顺序执行。看来我的表达方式很有问题啊。
bdmh 2011-08-05
  • 打赏
  • 举报
回复
你不能改变 p的指向,但可以改变p地址的实际值
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
这里我主要想谈论 指针传递为啥非要说是传递的副本,我这只是个例子,也许不大好。麻烦看下我说的话,也许字太多难看了点
xiaoguangzaia 2011-08-05
  • 打赏
  • 举报
回复
有点看不懂,你在函数里面有p = &全局变量了,那么下面改变*p当然改变的就是这个全局变量了
所以你这个函数根本没必要有参数,参数传进来就被你扔掉了
yah606060 2011-08-05
  • 打赏
  • 举报
回复
#include<iostream>


void passParamType(char * p)// 在使用指针作为参数的时候 其实也做了拷贝 只是这个*p 和原来那个
{ p = new char('d'); // *p 指向的地址相同 而本身指针的值是不同的
*p = 'a';
}



void passParam2Type(char ** p) // 这里的p 是一个指向指针变量的指针 在使用的时候传入的的是指针
{ //是指针变量这个变量本身的地址 而不是指针中的值
// p = 这里能直接用非指针变量赋值的给p
**p = 'a';// *p指向的是 传入指针 不是这个指针的拷贝 所以 **p能 成功赋值
}

int _tmain(int argc, _TCHAR* argv[])
{
char* p = new char('c');

passParamType(p);
std::cout << p << std::endl;

char* p2 = new char('c');
std::cout << &p2 << std::endl;
passParam2Type(&p2);
std::cout << p2 << std::endl;
std::cout << &p2 << std::endl;

char p1 = 'c';
passParamType(&p1);
std::cout << p1 << std::endl;
int i;
std::cin >> i;

}

在使用指针的时候一定要把指针当做是一种变量类型
yah606060 2011-08-05
  • 打赏
  • 举报
回复
#include<iostream>


void passParamType(char * p)// 在使用指针作为参数的时候 其实也做了拷贝 只是这个*p 和原来那个
{ p = new char('d'); // *p 指向的地址相同 而本身指针的值是不同的
*p = 'a';
}



void passParam2Type(char ** p) // 这里的p 是一个指向指针变量的指针 在使用的时候传入的的是指针
{ //是指针变量这个变量本身的地址 而不是指针中的值
// p = 这里能直接用非指针变量赋值的给p
**p = 'a';// *p指向的是 传入指针 不是这个指针的拷贝 所以 **p能 成功赋值
}

int _tmain(int argc, _TCHAR* argv[])
{
char* p = new char('c');

passParamType(p);
std::cout << p << std::endl;

char* p2 = new char('c');
std::cout << &p2 << std::endl;
passParam2Type(&p2);
std::cout << p2 << std::endl;
std::cout << &p2 << std::endl;

char p1 = 'c';
passParamType(&p1);
std::cout << p1 << std::endl;
int i;
std::cin >> i;

}

在使用指针的时候一定要把指针当做是一种变量
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
高手们都来发表下看法啊,别那么吝啬嘛
奋斗小青年 2011-08-05
  • 打赏
  • 举报
回复
大家都来发表下看法啥,呵呵
加载更多回复(1)
1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C中可变参数函数实现 38 8. C程序内存中组成部分 41 9. C编程拾粹 42 10. C语言中实现数组的动态增长 44 11. C语言中的位运算 46 12. 浮点数的存储格式: 50 13. 位域 58 14. C语言函数二维数组递方法 64 15. C语言复杂表达式的执行步骤 66 16. C语言字符串函数大全 68 17. C语言宏定义技巧 89 18. C语言实现动态数组 100 19. C语言笔试-运算符和表达式 104 20. C语言编程准则之稳定篇 107 21. C语言编程常见问题分析 108 22. C语言编程易犯毛病集合 112 23. C语言缺陷与陷阱(笔记) 119 24. C语言防止缓冲区溢出方法 126 25. C语言高效编程秘籍 128 26. C运算符优先级口诀 133 27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33. 二叉树的数据结构 167 34. 位运算应用口诀和实例 170 35. 内存对齐与ANSI C中struct内存布局 173 36. 冒泡和选择排序实现 180 37. 函数指针数组与返回数组指针函数 186 38. 右左法则- 复杂指针解析 189 39. 回车和换行的区别 192 40. 堆和堆栈的区别 194 41. 堆和堆栈的区别 198 42. 如何写出专业的C头文件 202 43. 打造最快的Hash表 207 44. 指针与数组学习笔记 222 45. 数组不是指针 224 46. 标准C中字符串分割的方法 228 47. 汉诺塔源码 231 48. 洗牌算法 234 49. 深入理解C语言指针的奥秘 236 50. 游戏外挂的编写原理 254 51. 程序实例分析-为什么会陷入死循环 258 52. 空指针究竟指向了内存的哪个地方 260 53. 算术表达式的计算 265 54. 结构体对齐的具体含义 269 55. 连连看AI算法 274 56. 连连看寻路算法的思路 283 57. 重新认识:指向函数指针 288 58. 链表的源码 291 59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 346 65. C指针讲解 352 66. 关于指向指针指针 368 67. C/C++ 误区一:void main() 373 68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C和C++的区别是什么? 387 74. 无条件循环 388 75. 产生随机数的方法 389 76. 顺序表及其操作 390 77. 单链表的实现及其操作 391 78. 双向链表 395 79. 程序员数据结构笔记 399 80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

65,209

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧