(论)C语言中的函数的参数传递

来源:互联网 发布:软件服务板块龙头股 编辑:程序博客网 时间:2024/05/30 05:24

       最近在网上看到一些分享的面试题,而且之前面试也碰到过关于C语言方面的知识。考的比较多的就是关于C的指针问题。指针问题一般都考函数的指传递问题。比较经典的问题如下代码所示:

#include <stdio.h>#include <stdlib.h>#include <string.h>void createMalloc(char *s);int main(int argc, const char * argv[]){    // insert code here...    char *s = NULL;    createMalloc(s);    memset((void *)s, 0, sizeof(s));    strcpy(s, "Hello world!");    printf("s : %s", s);    free(s);    return 0;}void createMalloc(char *s) {    s = (char *)malloc(100);}

         这段代码是不能运行的。在createMalloc()函数中分配的内存地址并没有被传递回来,这个函数已经泄露了。虽然函数的参数是一个char *指针,但是效果还是值传递。传递过去的s指向的是NULL,到达createMalloc函数的也是NULL,然后createMalloc里s被赋值为新分配的内存首址,仅此而已,和main中的s一点关系也没有。

        我觉得这跟一直以来说为的函数的参数传递有两种“值传递”和“地址传递”有关。其实从函数的作用机制来说,一个过程调用另一个过程,所有的参数都是简单的拷贝一个值过去的,不论你传递的是什么,基础类型或者指针都一样。区别在于,你究竟将这个参数作为什么来处理?

        一、作为普通的参数指来使用。就像上面的代码一样,使用s这个变量名就好了,那么使用的就是s所代表的内存地址里存储的值(变量名其实是内存地址的别名),所做的修改也就仅对函数中的自动变量s有效,因为在传参的过程中,createMalloc函数已经将main.s的值拷贝到一个新的变量中了(虽然变量名还是s),所以所有的操作都只对这个新的内存区域有效,无法影响到main中的s。

        二、作为一个地址来处理。先来看对上面代码的修改版:

void createMalloc(char *s);int main(int argc, const char * argv[]){    // insert code here...    char *s = NULL;    s = (char *)&s;    createMalloc(s);    memset((void *)s, 0, sizeof(s));    strcpy(s, "Hello world!");    printf("s : %s", s);    free(s);    return 0;}void createMalloc(char *s) {    *s = (void *)malloc(100);}
               这个代码是可以运行出预期的结果(打印出“Hello world!")。主要的更改就是s = (char *)&s;和createMalloc函数中的更改。当我们在函数中使用*操作符时,说明我们是希望将变量所存储的值作为地址来使用。可以理解为,程序先读取变量(此处为s)中的值,然后找到这个值所指示的内存块,然后再修改这个内存块中的值。由于代码s = (char *)&s;的存在,让s存储了它自身的地址,所以main.s的地址被拷贝到了createMalloc.s中,然后使用*操作符,又地位到了main.s,这才使得createMalloc函数的修改能影响到main。


        总结一下:

        1.函数的参数传递其实只有一种统一的值拷贝形式。区别只在于你传递的是什么值,以及这个值在函数中是如何使用的。

        2.一个简单快速的识别方法是,看是否在被调用函数中使用了*操作符。当然这个方法比较低级,只能简单识别。如果情况复杂一点,还需要进一步确认。


        ps0:所使用的环境是xcode。

        ps1:第二段代码会有警告,原因在于一些类型的转换上。而且这段代码结构规划并不好,只是为了说明问题。另外要指出的是,所有的指针类型的大小都是地址总线的线宽,一般是32位和64位(我使用的机器是64的),不同的指针类型只是为了说明取值时该将它作何种类型,所以上面的代码还是有问题的,但这并不妨碍对主题的阐述说明。


       欢迎各位的交流,我也是菜鸟。

       路漫漫其修远兮,吾将上下而求索。

原创粉丝点击