灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:8178回复:0

C语言中函数和指针的参数传递

楼主#
更多 发布于:2014-10-21 12:04
最近写二叉树的数据结构实验,想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个例子讨论一下c语言中指针作为形参的函数中传递中隐藏的东西。
大家知道C++中有引用的概念,两个数据引用同一个数据,那么更改任意的一个都相当于更改了本体,那么另一个数据所对应的值也会改变,可是C中是没有这个概念的。所以就产生了一些东西。和我们本来想的有差别。

 
一、明确C语言中函数的入口:
C语言中函数的形参负责接收外部数据,那么数据究竟怎么进入函数的呢,其实我们在函数体内操作的形参只是传递进来参数的一个副本,也就是说这两个参数虽然名字一样,对应的值一样,但是他们两个对应的内存地址是不一样的,也就是说这就是两个“看上去一模一样”的完全不同的变量。
所以一定要知道,C语言中函数是值传递的,也就是说,C语言只能把值传给函数,而不能把你想要传递的变量完全的放进函数内部。
二、指针传递给函数:
指针作为一个特殊的东西,他的强大之处就在于指针可以直接修改内存地址上的数据。虽然指针特别强大,但是他也难逃函数的限制,你传递给函数一个指针,因为是值传递,那么你在函数体内的使用的形参指针也只是一个副本,只是一个指向的值和你传进来的那个指针一样的一个另外的一个变量。也就是说他和普通常量是没有区别的。
三、我想要达到引用的效果怎么实现
C语言中因为是值传递的,那么我们就传递值,只要讲想要传递进函数的东西的地址传进函数,并且函数用一个指针接收,那么就相当于把这个变量地址原封不动的传递给了函数,形参的指针指向的是外面传进来的地址,有了地址不就好办了吗。
四、下面是我写的一个二叉树建立的一个无返回值的版本:
因为二叉树是用递归建立的,就像建立链表一样,一个节点一个节点建立,如果不获得上一个节点的地址,你怎么把链表连接起来呢,链表就散开了。
所以只能通过传递地址来达到找到已经建好的链表的前驱,才能把各个节点穿起来。
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <stdlib.h>
 
typedef struct tree {
char t;
struct tree *lchild;
struct tree *rchild;
}Tree;
 
void initTree(Tree **T) {
char ch;
ch = getchar();
if (ch == '#') {
*T = NULL;
}
else {
*T = (Tree *)malloc(sizeof(Tree));
(*T)->t = ch;
initTree(&(*T)->lchild);
initTree(&(*T)->rchild);
}
}
 
void qianT(Tree *T) {
if (T) {
printf("%c ",T->t);
qianT(T->lchild);
qianT(T->rchild);
}
}
 
int main (void) {
Tree *T;
initTree(&T);
qianT(T);
return 0;
}
 
</stdlib.h></stdio.h>


注意看树的建立那个函数,我每次都是穿进去一个节点的地址,然后通过地址来找到已经建立好的树,才能将树建立起来。那么有的人会问了?为什么不是下面这个写法呢?
 
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
void initTree(Tree *T) {
char ch;
ch = getchar();
if (ch == '#') {
T = NULL;
}
else {
T = (Tree *)malloc(sizeof(Tree));
T->t = ch;
initTree(T->lchild);
initTree(T->rchild);
}
}
这种写法,你每次传进来的都是一个变量,说过,c语言是值传递的,那么每次你申请的节点空间都是给副本申请的,然后递归的是副本的左右孩子,也就是说你的树根本没有建立起来,因为每次申请的内存都没有连接上。
为什么我的那个写法可以呢,因为我是用一个指向指针的指针来存地址的,我给传进来的地址申请了内存,也就相当于给穿进来的那个节点本身申请了内存,而不是给副本,所以二叉树就顺其自然建立起来了。
最后记住,c语言是值传递的,任何东西传递给函数的都只是值!

喜欢0 评分0
游客

返回顶部