黑马程序员技术交流社区

标题: IOS第6期第一次技术活动 [打印本页]

作者: 张文文    时间: 2015-1-9 09:47
标题: IOS第6期第一次技术活动
今天是6期开版的第二天,相信在这个论坛下发帖,回复的都是为了进入第6期或者为日后进入黑马的人。大多数人都在用功的学习基础知识或者进行更深层次的研究。
今天,进行我们6期第一次基础知识技术活动,只要你的回复帖子能通过自己的理解,对这个知识点有独特的分析或者解答,就可以参加回复讨论。目的很简单,就是为了让大家各抒己见,共同进步。现在,步入正题!

题目:C语言中,函数参数的传递有3种形式。请大家谈谈其中两种,“值传递”和“地址传递”的理解吧。最好能通过代码分析。
作者: 三生三世    时间: 2015-1-9 10:09
支持!!看看大家都有什么神理解~(*^__^*)
作者: 晓风_残月    时间: 2015-1-9 10:31
值传递 :仅仅传递了值本身,相当于一个傀儡。傀儡做任何事情偶读不会影响到本体。

引用传递: 将本体传进去,是一个实体,做任何事都会影响到本体本身。
如此回答,不知道行不:lol
作者: 三生三世    时间: 2015-1-9 10:44
晓风_残月 发表于 2015-1-9 10:31
值传递 :仅仅传递了值本身,相当于一个傀儡。傀儡做任何事情偶读不会影响到本体。

引用传递: 将本体传进 ...

你地址传递解释得不对。地址传递是告诉你,值A存储在了哪里,然后你能根据A的地址,去那里找到它,并且修改它,并不是获取本体。
作者: frozen    时间: 2015-1-9 10:49
值传递,函数不能改变实参的值,地址传递,也就是通过指针,可以通过地址改变实参所在单元的值
作者: 王德亮    时间: 2015-1-9 11:29
以两个整数的交换为例
  1. #import <Foundation/Foundation.h>
  2. #import <stdio.h>
  3. // 利用值传递进行两个整数的交换的函数
  4. void changeByValue(int a, int b)
  5. {
  6.     int tmp;
  7.     tmp = a;  // 交换两个数
  8.     a = b;
  9.     b = tmp;
  10. }
  11. // 利用指针进行地址传递交换两个整数的函数
  12. void changeByPoint(int *a,int *b)
  13. {
  14.     int tmp;
  15.     tmp = *a;
  16.     *a = *b;
  17.     *b =tmp;
  18. }
  19. int main()
  20. {
  21.     int a = 4, b = 5;
  22.    
  23.     changeByValue(a,b);
  24.     // 打印调用值传递函数后a,b的值
  25.     printf("After call changeByValue:a = %d,b = %d\n",a,b);
  26.    
  27.     changeByPoint(&a,&b);
  28.     // 打印地址传递函数后a,b的值
  29.     printf("After call changeByPoint:a = %d, b = %d\n",a,b);
  30. }
复制代码

打印结果为:
After call changeByValue:a = 4,b = 5
After call changeByPoint:a = 5, b = 4
值传递的过程中 changeByValue函数得到的a,b只是原来变量a,b的拷贝,虽然在函数内部交换了a,b的值,但是事实上并没有改变a,b变量的值
而利用地址传递,顾名思义传递的是变量地址,所以在changeByPoint函数中,利用*操作符,操作的是存放变量a,b的内存地址上的东西。
感觉重点是不要被变量的名称迷惑即使都叫a,b,但是所对应的内存地址是不同的。
作者: 仰望的繁华    时间: 2015-1-9 11:35
本帖最后由 仰望的繁华 于 2015-1-9 12:01 编辑

转行无基础,平时你们讨论的内容我都还没学到。难得这次问视频里看过的内容。
我就来努力回答一下,当做督促自己吧~

首先我的基本理解是:
1. 值传递:
    就像抄作业,你把我的作业内容抄走,作业抄在你本子上的时候内容是一样的,抄走之后就是各自手里拿着各自的作业本,你再怎么修改你的作业,变化都在你的作业本上,我的作业本依然在我手里,上面的内容还是老样子。
2. 地址传递:
    就像寻找宝藏,每个人都可以把藏宝地图抄走,但是抄走之后的藏宝图,指向的还是同一个宝藏。一旦有人按照藏宝图指示的地点改变了宝藏内容,其他人再根据藏宝图找到宝藏的时候,都是前面的人改变之后的宝藏。
    然后引申一下:如果有多个宝藏,抄不同藏宝图的人自然找到不同的宝藏。如果手里已经有图了,再抄相同的图指向宝藏不变,抄不同的图则指向新的宝藏。

3. 关于 值传递 自学时看的例子:
  1. #include <stdio.h>
  2. void exChange(int x, int y)
  3. {
  4.         int temp = 0;
  5.         temp = x;
  6.         x = y;
  7.         y = temp;
  8.         printf("x=%d, y=%d\n", x, y);
  9. }
  10. int main()
  11. {
  12.         int a = 1;
  13.         int b = 2;
  14.         exChange(a, b);
  15.         printf("a=%d, b=%d\n", a, b);
  16. }
复制代码
理解过程:main—>a作业本写完:1,b作业本写完:2
—>xy对应抄走ab作业—>此时x和a作业相同,y和b作业相同。
—>xy交换作业本
—>此时x手里拿的作业和b相同:2,y拿的和a相同:1。
—>而此时a的作业本仍然写的:1,b的仍然写的:2

3. 关于 地址传递 自学时看的例子:
  1. #include <stdio.h>
  2. void exChange(int *p1, int *p2)
  3. {
  4.         int temp = *p1;
  5.         *p1 = *p2;
  6.         *p2 = temp;
  7.         printf("*p1=%d, *p2=%d\n", *p1, *p2);
  8. }
  9. int main()
  10. {
  11.         int a = 1;
  12.         int b = 2;
  13.         exChange(&a, &b);
  14.         printf("a=%d, b=%d\n", a, b);
  15. }
复制代码

理解:
main—>a将自己的宝藏1画在藏宝图*p1上,b将宝藏2画在*p2上
—>日后各自根据*p1可找到宝藏1,根据*p2可找到宝藏2
—>exChange把*p1和*p2两张图纸内容互换
—>互换后,*p1和原来*p2图示相同,*p2和原来*p1相同
—>此时,*p1指向宝藏2,*p2指向宝藏1,a拿着*p1找到宝藏2,b拿着*p2找到宝藏1

以我的初学水平也就理解到这种程度。
欢迎指证~







作者: 邓明    时间: 2015-1-9 12:25
王德亮 发表于 2015-1-9 11:29
以两个整数的交换为例

打印结果为:

代码分析的很好
值传递就是单纯的拷贝,在函数的内存空间内开辟了一块区域用于存储拷贝进来的值,并不是函数外部的变量,作用域受限于代码段内部,出了代码段这些值就会从内存中被释放掉,所以值传递对于代码段外部的实参是没有作用的
而地址传递其实就是指针,则相当于直接将值的“门牌号”,也就是实际内存地址告诉了函数,因此函数内部可以根据“门牌号”便可对函数外部的值进行访问或修改
作者: dormitory219    时间: 2015-1-9 12:44
总所周知,函数实参可通过值和地址传递给形参:
1.值传递:通过函数形参和实参来传递基本类型(int,float,char)变量值的话,函数调用后,形参的改变不会影响实参的改变;

2.地址传递呢:可通过数组,指针来进行传递,
2.1数组传递:实参数组将首地址传递给函数形参后,函数形参数组就和实参数组就共享了同一个地址,改变形参数组中元素值,函数调用后,相应实参数组中的元素也就发生了变化;

2.2指针传递:实参将地址传递给形参后,可通过形参来改变实参的内容,
我们常见的两个数交换,如果要通过函数来实现,通过值传递并不能达到实参交换的效果,而通过地址传递,则可以达到这种效果;

关于数组地址传递,我发现,数组是个比较搞的,如果你是直接在main函数中定义两个数组,要两个数组相同的话,直接赋值首地址给对方的话,是不允许的,因为地址是常量,但是在函数是可以函数实参数组首地址传递首地址给形参数组的;

哈哈,这是我的见解,初学者,多多包涵。
作者: tim_taopeng    时间: 2015-1-9 15:09
看大家的学习一下
作者: tim_taopeng    时间: 2015-1-9 15:13
看大家的学习一下
作者: 晓风_残月    时间: 2015-1-9 15:33
三生三世 发表于 2015-1-9 10:44
你地址传递解释得不对。地址传递是告诉你,值A存储在了哪里,然后你能根据A的地址,去那里找到它,并且修 ...

嗯,是了。意思都是 地址传递 变量修改了之后都能够改变的。我表述不是太好。呵呵
作者: 郑江    时间: 2015-1-9 18:07
我觉得地址传递是一种特殊的值传递
相同点:他们都是将某个常量值作为实参传递到函数形参中
              在函数内部修改该常量值,不会影响函数外的数据。
不同点:当传递的常量值为地址值的时候,可以用一元运算符*
             通过该地址值找到函数外部变量并修改。
#include <stdio.h>
void test (int *p1)
{
      /*将10赋值给p1所指向的对象a
         此时a == 10, p == p1 == &a ; */
      *p1 = 10;
      int b = 1;
      /*将b的地址值赋值给p1,p值不会变化
          此时p == &a,   p1 == &b ; */
      p1 = &b;
}  // 函数运行完毕,指针变量p1和变量b均被销毁
int main()
{
      int a = 5;
      int *p = &n;
      // 调用test函数,并将指针变量p的值(即n的地址值)赋值给p1
      test(p);   
      return 0;   
}



作者: 张传宾    时间: 2015-1-9 18:10
王德亮 发表于 2015-1-9 11:29
以两个整数的交换为例

打印结果为:

你讲的对
作者: zyp115    时间: 2015-1-9 18:43
本帖最后由 zyp115 于 2015-1-9 18:49 编辑

额,值互换的C代码怎么用上oc声明写,刚看oc,看到数组就想说,定义指针指向数组可以p++,但数组a[]本身不能a++
作者: macau    时间: 2015-1-9 19:57
上面的a是常量,代表数组首元素的地址不能进行a++
作者: ocean45    时间: 2015-1-9 20:08
主要是一个按值传递,函数不能改变实参的值,一个按地址传递,通过指针,也可以通过地址改变实参所在单元的值。昨天刚刚考过类似的,不过在C++中。
作者: Dance小飞    时间: 2015-1-10 00:34
已经在考试流程中,但是自己的基础确实不怎么好,基础测试有几个题都不会,已经要加油
作者: 枫华绝代    时间: 2015-1-10 00:48
函数在传递的过程中本质都是复制参数的值,而值传递就是复制参数本身的值,地址传递就是复制值的地址. 而要想访问原参数的值需要的只能是地址,这就好比是房间钥匙.
值传递的本质是复制一栋房子给你,但是你终究没有原房子的地址,你可以随意捣鼓这个克隆的玩意儿,但是一辈子也无法进入本体房子
地址传递的本质是将钥匙复制一份给你,告诉你这是XXX房间的钥匙,你可以用钥匙去房间为所欲为.
值传递安全,没有后顾之忧,完全不会担心暴露本体
地址传递不安全,会暴露和改变本体
函数到底按什么传递,还需要按需分配.
作者: mengxingdong    时间: 2015-1-10 15:31
值传递是对传入参数的复制,当函数结束时,不改变传入参数的值。地址传递是传入参数的地址,函数结束后回改变传入参数的值
作者: woaiwomama    时间: 2015-1-10 20:11
值传递只能是单向传递,由实参传给形参,
作者: 歧路    时间: 2015-1-10 20:45
  1. #include <stdio.h>
  2. int sum(int num1,int num2)
  3. {
  4.     num1=30;  //如果是基本数据类型作为函数参数,纯粹是值传递,修改函数内部形参的值,并不会影响外面实参的值
  5.     return num1+num2;
  6. }
  7. int sum1(int *p1,int *p2)
  8. {
  9.     *p1=11;//这里是指针作为函数参数,是地址传递,修改指针指向的地址的参数的值,,会改变外面的实参的值
  10.     return *p1 + *p2;
  11. }
  12. int main(int argc, const char * argv[]) {

  13.         int a=1;
  14.         int b=2;
  15.         int c=sum(a,b);
  16.         printf("%d %d %d\n",a,b,c);
  17.         int *p;
  18.         p= &a;
  19.         int *p1;
  20.         p1= &b;
  21.         int c2 = sum1(p, p1);
  22.         printf("%d %d %d\n",a,b,c2);

  23.     return 0;
  24. }
复制代码

作者: 满大街的谎言。    时间: 2015-1-10 20:46
哇,都好棒啊。
作者: 枫煠    时间: 2015-1-10 21:53
本帖最后由 枫煠 于 2015-1-10 21:56 编辑
  1. void swapValue(int x, int y){
  2.     printf("值传递之前 : x=%d,y=%d\n",x,y);
  3.     int temp = 0;
  4.     temp = x;
  5.     x = y;
  6.     y = temp;
  7.     printf("值传递之后 : x=%d,y=%d\n",x,y);
  8. }

  9. void swapAddress(int *x, int *y){
  10.     int temp = 0;
  11.     temp = *x;
  12.     *x = *y;
  13.     *y = temp;
  14. }

  15. int main(int argc, const char * argv[]) {
  16.     @autoreleasepool {
  17.         // insert code here...
  18.         
  19.         int x = 20,y =30;
  20.         
  21.         swapValue(x,y);
  22.         
  23.         printf("地址传递之前 : x=%d,y=%d\n",x,y);
  24.         swapAddress(&x,&y);
  25.         printf("地址传递之前 : x=%d,y=%d\n",x,y);
  26.     }
  27.     return 0;
  28. }{
复制代码
用白话一点的解释就是



作者: Dance小飞    时间: 2015-1-11 00:19
大家都一起努力加油
作者: 刘俊龙    时间: 2015-1-11 09:58
还是前段时间时间看的视频,有点记不清了,只记得形参的改变不会改变实参
作者: liu1170486003    时间: 2015-1-11 14:16
值传递:将参数的值copy一份传递过去
引用传递:将参数的内存地址传递过去,直接对地址内的值进行改变
作者: 忆昔稠    时间: 2015-1-11 14:33
值传递只是改变了新开辟的地址空间中的内容,函数一执行完毕释放空间,原函数的值并没有改变。而地址传递操作的是传递的是指针,所以交换后指向的对象改变,也就是改变了参数的内容
作者: 曼珠沙华    时间: 2015-1-11 18:23
第6期终于开版了,恭喜
作者: lgh1992314    时间: 2015-1-11 19:01
参数传递有三种:1、传值   2、传地址   3、传引用(本质上等同于传地址:指针常量)
  1. void swapbyValue(int x, int y)
  2. {
  3.         int temp = x;
  4.         x = y;
  5.         y = temp;
  6. }

  7. void swapbyReference(int &x, int &y)
  8. {
  9.         int temp = x;
  10.         x = y;
  11.         y = temp;
  12. }

  13. void swapbyPoint(int* x, int* y)
  14. {
  15.         int temp = *x;
  16.         *x = *y;
  17.         *y = temp;
  18. }
复制代码

做到真正深刻理解,恤借助于编辑器。
类似1、传值


环境:VS2013 F5调试 F11步进得到的结果


可见传值实参。形参存储在不同的空间,交换是互不影响的。
传地址、传引用类似。

作者: haojuncong    时间: 2015-1-11 23:58
我的理解是:基本数据类型都是值传递。数组对象等名称代表地址的都是地址传递
作者: Dance小飞    时间: 2015-1-12 01:07
确实是,痛并快乐着
作者: yuanlingqi    时间: 2015-1-12 09:17
支持,必须的,期待进黑马
作者: 刘俊龙    时间: 2015-1-12 10:34
看完视频再看这些,理解的更透彻了
作者: foduyouyuan    时间: 2015-1-12 11:45
努力,让自己不要再后悔一次......
作者: 北漂的小马    时间: 2015-1-12 16:10
加油   必须要改变自己
作者: 13hoop    时间: 2015-1-12 16:13
其实不管是传值还是传地址
对于所传参数本质上都要进行相应参数的拷贝  这是函数为了不影响原值的一种安全规定
传值就是复制数值 传地址就有指针变量负责复制地址
用经典的书名和书架的例子
传只好比重新抄写了这本要用的本书
而传地址就是记下了这本书在书架的第几行第几列的位置
根据这个位置找到相应的书即可
但是值传递比地址传递通常来说更安全  而地址操作相对高效  要依情况取舍使用
作者: 松果    时间: 2015-1-12 16:41
学习了  大家都加油
作者: QYMHS    时间: 2015-1-12 17:47
基础很重要啊!
作者: 行我福    时间: 2015-1-27 10:42
2楼正解,说的很详细。
作者: alin000    时间: 2015-1-27 16:42
值传递只是传递变量的值给函数,函数运行结束后,传递的变量不会改变
地址传递是传递保存变量的地址,如果在函数中改变了,外面变量的值也会改变
作者: dawsper    时间: 2015-1-27 16:47
前排围观
作者: Adam_Eve    时间: 2015-1-27 17:42
大家已经说完了 ,还让我怎么说啊?:'(
作者: 临汾皮皮    时间: 2015-1-27 17:47
你们都好牛,小弟受教了
作者: qq5591916    时间: 2015-1-27 19:18
越学越晕了。。。。。。。。。。。。。。。。。
作者: 备战黑马五期    时间: 2015-1-27 19:34
值传递,在指针中只是把函数在内存的地址传递了,然后通过地址改变里边的数值。指针就是储存地址。
作者: 水木清华hm    时间: 2015-1-27 20:02
我是来看评论的,哈哈
作者: 仰望星空.....    时间: 2015-1-31 13:21
  1.         <p>
  2.                 C语言中函数参数的传递有:值传递、地址传递、引用传递这三种形式。
  3.         </p>
  4.         <p>
  5.                 按值传递--子函数在内存开辟一个临时空间,将传递的实参访问这个空间,当子函数结束后,这个内存空间就会释放。
  6.         </p>
  7.         <p>
  8.                 地址传递--主函数开辟的某个内存空间首地址传递给子函数,子函数可以直接访问主函数上这段内存空间,
  9.                 当子函数结束后,这部分空间不会被释放,主函数可继续使用这段空间。
  10.         </p>       
  11.         <p>
  12.                 引用传递--子函数在内存开辟一个临时空间,将传递的实参的地址值访问这个空间,当子函数结束后,这个内存空间就会释放。
  13.         </p>
  14.         <tr>
  15.                 <td>还请大家指正!!
  16.         </td>
  17.         </tr>
复制代码

作者: 1026238004    时间: 2015-1-31 22:32
学习了!
作者: 理工007    时间: 2015-2-1 00:04
学习了,很好
作者: Zeus-S    时间: 2015-2-1 11:24
我就是进来学习的,好多见解真好




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2