作为任意一个C语言的学习者都明白这样一个规定,在函数中实参变量对形参变量的数据传递是“单向值传递”,只由实参传给形参,不能由形参传回给实参。
作为这样一个人尽皆知的道理,前两天却遇到了这样的问题。同学忽然问我一个关于数组初始化的问题,问说为什么在初始化函数中无法正确实现数组元素的初始化,看了他的代码感觉问题存在于初始化子函数中分配了堆空间,便让他把分配空间的步骤移到主函数中,结果正确,但我自己却产生疑惑了,这个现象出现的具体原因是什么,于是便写了一下测试小例子:
#include
#include
void init(int *,int);
void point(int *);
struct my_struct
{
int a;
char *c;
};
void test_struct(struct my_struct *my)
{
char *str = "hello world";
printf("%d\t%p\n",&(my->a),&(my->c));
my->a = 1;
my->c = malloc(20);
strcpy(my->c,str);
printf("%d\t%s\n",my->a,my->c);
printf("%d\t%p\n",&(my->a),&(my->c));
}
int main(void)
{
int *array;
int test=0;
struct my_struct my;
init(array,2);
printf("%d\t%d\n",*array,*(array+1));
point(&test);
printf("%d\n",test);
test_struct(&my);
printf("%d\t%s\n",my.a,my.c);
return 0;
}
void init(int *array,int n)
{
array=(int *)malloc(2);
*array=2;
*(array+1)=2;
printf("test value %d\t%d\n",*array,*(array+1));
return ;
}
void point(int *num)
{
num=(int *)malloc(1*sizeof(int));
*num=3;
return ;
}
void point(int *num)
{
*num=3;
return ;
}
正如预料的,第一条printf语句无法打印出初始数值2,第2个函数能够打印出初始值3.
关于这个问题,其实很容易理解,这里面主要涉及到两方面的知识:系统内存堆栈空间分配和刚所说的参数传递。
栈中存放函数的参数和函数局部变量的值,堆则是由程序员自己分配和释放,堆和栈位于不同的地址空间范围中。在测试函数中,main()函数中的array指针为临时变量,存放在栈中,经init()函数参数传递后将其值赋给形参变量,在子函数中又讲过malloc()分配堆空间,此时返回地址为堆上的新地址,等于在这个时候已经改变了形参array的值,这时由于C语言中的参数传递机制,子函数中形参值的改变不会反应在main函数中,所以在main函数中不能显示出初始化的结果。而子函数point()则无这方面的问题。
总的来说,如果你需要在子函数中改变主函数的变量值,就必须传递此变量的地址,不管此变量是否为指针。所以,在测试函数中,只需将init函数的参数改为init(int **arr,int n)即可,这个问题也就暂时告一段落。
在此测试函数中,仍存在一个问题,在主函数中分配的指针并未初始化,期所指向的值属于未确定,在这样的情况下,Linux下不允许直接改变其所指向的值,运行时会出现段错误。这一点也需要注意.
为什么在结构体作为参数时,结构体的字符串变量在malloc变量之后的地址值没有发生改变呢,有些疑惑
若在main函数中定义结构体的指针的话,将此指针传进子函数时,会因为对位初始化的指针赋值而产生段错误。
什么个情况呢? 明天搞定!!
应该是这样理解的,结构体中字符串变量的my->c的值在malloc之后发生了变化,只不过在测试语句中的打印打印的是&(my->c),它的类型为char **,它的值取决于结构体struct my的地址,在这里可以这样简单的理解,我们在test_struct中传递了两个参数,一个是int *a,一个是char **c,他们是两个指针,也就是两个地址,然后紧接着我们对*a = 1; *c = malloc(20); 在这里只是改变了这两个指针所指向的值,并没有对地址(也就是形参)作出修改,所以所作的改变时能够反映到主函数中的。
对于这个问题,最简单可以这样理解,我们参数传递的是结构体的指针,即其地址值,我们这里只是对其内部的变量作出修改,并没有改变结构体的地址值,所以修改时可以返回的
应该就是这个样子了。。。
阅读(1092) | 评论(0) | 转发(0) |