A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张文文 中级黑马   /  2015-1-9 09:47  /  5625 人查看  /  51 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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

题目:C语言中,函数参数的传递有3种形式。请大家谈谈其中两种,“值传递”和“地址传递”的理解吧。最好能通过代码分析。

评分

参与人数 1黑马币 +1 收起 理由
天空总是很蓝 + 1 很给力!

查看全部评分

51 个回复

倒序浏览
支持!!看看大家都有什么神理解~(*^__^*)

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
值传递 :仅仅传递了值本身,相当于一个傀儡。傀儡做任何事情偶读不会影响到本体。

引用传递: 将本体传进去,是一个实体,做任何事都会影响到本体本身。
如此回答,不知道行不:lol

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
晓风_残月 发表于 2015-1-9 10:31
值传递 :仅仅传递了值本身,相当于一个傀儡。傀儡做任何事情偶读不会影响到本体。

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

你地址传递解释得不对。地址传递是告诉你,值A存储在了哪里,然后你能根据A的地址,去那里找到它,并且修改它,并不是获取本体。
回复 使用道具 举报
值传递,函数不能改变实参的值,地址传递,也就是通过指针,可以通过地址改变实参所在单元的值

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
以两个整数的交换为例
  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,但是所对应的内存地址是不同的。

评分

参与人数 1黑马币 +2 收起 理由
张文文 + 2

查看全部评分

回复 使用道具 举报 2 0
本帖最后由 仰望的繁华 于 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

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






评分

参与人数 1黑马币 +2 收起 理由
张文文 + 2

查看全部评分

回复 使用道具 举报 1 0
王德亮 发表于 2015-1-9 11:29
以两个整数的交换为例

打印结果为:

代码分析的很好
值传递就是单纯的拷贝,在函数的内存空间内开辟了一块区域用于存储拷贝进来的值,并不是函数外部的变量,作用域受限于代码段内部,出了代码段这些值就会从内存中被释放掉,所以值传递对于代码段外部的实参是没有作用的
而地址传递其实就是指针,则相当于直接将值的“门牌号”,也就是实际内存地址告诉了函数,因此函数内部可以根据“门牌号”便可对函数外部的值进行访问或修改

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
总所周知,函数实参可通过值和地址传递给形参:
1.值传递:通过函数形参和实参来传递基本类型(int,float,char)变量值的话,函数调用后,形参的改变不会影响实参的改变;

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

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

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

哈哈,这是我的见解,初学者,多多包涵。

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
看大家的学习一下

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
看大家的学习一下
回复 使用道具 举报
三生三世 发表于 2015-1-9 10:44
你地址传递解释得不对。地址传递是告诉你,值A存储在了哪里,然后你能根据A的地址,去那里找到它,并且修 ...

嗯,是了。意思都是 地址传递 变量修改了之后都能够改变的。我表述不是太好。呵呵
回复 使用道具 举报
我觉得地址传递是一种特殊的值传递
相同点:他们都是将某个常量值作为实参传递到函数形参中
              在函数内部修改该常量值,不会影响函数外的数据。
不同点:当传递的常量值为地址值的时候,可以用一元运算符*
             通过该地址值找到函数外部变量并修改。
#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;   
}


评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
王德亮 发表于 2015-1-9 11:29
以两个整数的交换为例

打印结果为:

你讲的对

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 zyp115 于 2015-1-9 18:49 编辑

额,值互换的C代码怎么用上oc声明写,刚看oc,看到数组就想说,定义指针指向数组可以p++,但数组a[]本身不能a++

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
上面的a是常量,代表数组首元素的地址不能进行a++

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
主要是一个按值传递,函数不能改变实参的值,一个按地址传递,通过指针,也可以通过地址改变实参所在单元的值。昨天刚刚考过类似的,不过在C++中。

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
已经在考试流程中,但是自己的基础确实不怎么好,基础测试有几个题都不会,已经要加油

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
函数在传递的过程中本质都是复制参数的值,而值传递就是复制参数本身的值,地址传递就是复制值的地址. 而要想访问原参数的值需要的只能是地址,这就好比是房间钥匙.
值传递的本质是复制一栋房子给你,但是你终究没有原房子的地址,你可以随意捣鼓这个克隆的玩意儿,但是一辈子也无法进入本体房子
地址传递的本质是将钥匙复制一份给你,告诉你这是XXX房间的钥匙,你可以用钥匙去房间为所欲为.
值传递安全,没有后顾之忧,完全不会担心暴露本体
地址传递不安全,会暴露和改变本体
函数到底按什么传递,还需要按需分配.

评分

参与人数 1黑马币 +2 收起 理由
张文文 + 2

查看全部评分

回复 使用道具 举报
值传递是对传入参数的复制,当函数结束时,不改变传入参数的值。地址传递是传入参数的地址,函数结束后回改变传入参数的值

评分

参与人数 1黑马币 +1 收起 理由
张文文 + 1

查看全部评分

回复 使用道具 举报
123下一页
您需要登录后才可以回帖 登录 | 加入黑马