c入门第九篇——为什么我还是之前的我?(传值与传址)

有一天师弟兴冲冲的跑过来和我说:“师兄,我发现c语言设计存在一个bug。”
我问到:“什么bug呢?”
师弟说道:“你看我这段程序,没有生效。”
我笑着说到:“难道没有可能是你写的代码有问题?”
师弟说:“不会,我检查了好几遍了,这么简单的代码应该不会有问题的。”
我说:“那好,我们就简单分析一下。”

师弟的代码

#include 
#include 

/**
 * add - 求两个整数的和
 * @a: 一个有效int数据
 * @b: 一个有效int数据
 * @sum: 有个int数和
 *
 * Returns:   0 on success
 *           -1 on error
 */
int add(int a, int b, int sum) {
    if (((long long int)a + (long long int)b) > INT32_MAX) {
        return -1;
    }

    sum = a + b;
    return 0;
}

int main()
{
    int a, b, sum = 0, ret;

    scanf("%d %d", &a, &b);
    ret = add(a, b, sum);
    if (!ret) { //没有溢出时,输出2个数的和
        printf("%d + %d = %d\n", a, b, sum);
    } else { //溢出时,打印不支持
        printf("sum is overflow, no support!\n");
    }

    return 0;
}

最后代码执行,sum输出是0,而不是a + b的和。有一种“他强任他强,清风拂山岗;他横由他横,明月照大江。”我还是我之感。
add函数,将sum值传入到函数中,却没有将sum值带回,为什么呢?
这里其实是典型的传值和传址的问题。

传值(pass by value)和传址(pass by reference)是函数调用的两种参数传递方式。传值意味着函数接收的是变量的副本,因此在函数内部对参数所做的修改,不会影响到原始变量。传址意味着函数接收的是变量地址的副本(通常使用指针),因此在函数内部对参数所做的修改,会影响到原始变量。

当前这个情况就是,将sum的值传给了形参,而并没有将地址传给形参。
修正的方法也比较简单,如下,只需把sum的地址传入就行。

#include 
#include 

int add(int a, int b, int *sum) { //接收sum的地址
    if (((long long int)a + (long long int)b) > INT32_MAX) {
        return -1;
    }

    *sum = a + b;
    return 0;
}

int main()
{
    int a, b, sum, ret;

    scanf("%d %d", &a, &b);
    ret = add(a, b, &sum); //传入sum的地址
    if (!ret) {
        printf("%d + %d = %d\n", a, b, sum);
    } else {
        printf("sum is overflow, no support!\n");
    }

    return 0;
}

这里只是简单的传值和传址的示例,当遇到更加复杂的双重指针问题时,很多时候容易被绕错。当发现存在修改值失效时,就需要考虑自己是不是传参存在问题了。师弟挠了挠脑袋,不好意思的笑着说道:“我二了,还是回去继续学习去”。

你可能感兴趣的:(c语言入门,c语言,算法,开发语言)