传递值和参考之间的混淆?

时间:2009-06-29 18:32:18

标签: c

有人可以解释为什么这不起作用吗?

int main()
{
    float* x;
    float a, b;
    int num_vals = 10;

    fill_in_x(&x, num_vals); // malloc is called and x is populated with values

    a = x[0];
    b = x[1] - x[0];

    printf("%f\n", a);
    printf("%f\n", b);

    function_using_a_and_b(a, b); // The values of a and b used in this function 
                                  // don't match those calculated in main 
}

void fill_in_x(float** x, int num_vals)
{
    *x = (float*)malloc(num_vals * sizeof(float));

    // Fill in values for x
}

void function_using_a_and_b(float a, float b)
{
    printf("%f\n", a);
    printf("%f\n", b);
}

重申注释中的内容,当我在一个单独的函数中为malloc动态分配x的内存时,尝试将几个值传递给另一个函数,这些值不能正确传递。感觉就像一个指向问题,但我认为我传递的是a和b的值,而不是地址。为了记录,我甚至尝试使用memcpy将值放在a和b中,但这也没有做到。

我确实通过传递a和b的地址然后在function_using_a_and_b中取消引用它来使它工作,但为什么上面的方法不起作用?

提前致谢。

11 个答案:

答案 0 :(得分:3)

为了让malloc在你的fill_in_x()函数中工作,你需要将指针传递给函数,而不是指针的引用。关于传递引用和传递值之间的问题,传递值涉及函数制作变量的本地副本,而传递引用则是指针传递的更具体类型,通过here更好地解释。忽略它适用于C ++,因为对于你的问题,它的工作方式与C相同。

答案 1 :(得分:2)

你很可能在fill_in_x中做了一些不正确的事情。由于定义不在帖子中,我不能说什么,但它应该是这样的:

void fill_in_x(float** array) {
      *array = (float*) malloc(10*sizeof(float));
}

(虽然返回已分配的内存是不好的形式,因为它经常会导致内存泄漏,例如代码中的内存泄漏。)


(响应fill_in_x):在visual studio上编译并运行此代码会产生预期的输出。

#include <stdio.h>
#include <stdlib.h>

void fill_in_x(float** x, int num_vals)
{
    *x = (float*)malloc(num_vals * sizeof(float));

    for(int i = 0; i < num_vals; ++i)
        (*x)[i] = (i*2)+3;
}

void function_using_a_and_b(float a, float b)
{
    printf("%f\n", a);
    printf("%f\n", b);
}

int main()
{
    float* x;
    float a, b;
    int num_vals = 10;

    fill_in_x(&x, num_vals); // malloc is called and x is populated with values

    a = x[0];
    b = x[1] - x[0];

    printf("%f\n", a);
    printf("%f\n", b);

    function_using_a_and_b(a, b); // The values of a and b used in this function 
                                  // don't match those calculated in main 
}

写入:

3.000000
2.000000
3.000000
2.000000

所以我仍然不确定你的意思。我怀疑帖子中仍然缺少有问题的代码。

答案 2 :(得分:2)

这看起来像我期望的那样有效:

#include <stdlib.h>
#include <stdio.h>

void fill_in_x(float** x, int num_vals)
{
    float* res = (float*)malloc(num_vals * sizeof(float));
    *x = res;

    // Fill in values for x
    res[0] = 1.0;
    res[1] = 4.0;
}

void function_using_a_and_b(float a, float b)
{
    printf("%f\n", a);
    printf("%f\n", b);
}

int main()
{
    float* x;
    float a, b;
    int num_vals = 10;

    fill_in_x(&x, num_vals); // malloc is called and x is populated with values

    a = x[0];
    b = x[1] - x[0];

    function_using_a_and_b(a, b); // The values of a and b used in this function 
                                  // don't match those calculated in main 
}

答案 3 :(得分:1)

您可以尝试调试函数fill_X,并在函数的主内部和内部观察f地址。

另一种方法是将fill_x函数更改为

float* fill_x(){

  float* f = malloc(...);

  //do stuff with f.

  return f;

}

然后你必须释放那个记忆

 float *f = fill_x();

  //do stuff with f.
  free(f);

答案 4 :(得分:0)

如果函数需要修改给定参数的值,则需要为其指定地址。否则它会在a和b中创建值的新本地副本并修改它们。

答案 5 :(得分:0)

如果有点奇怪的话,你所做的事情看起来是正确的。

我唯一担心的是你没有展示足够的fill_in_x代码,以便我们了解你正在填写的内容。

 // Fill in values for x

这里有可能你做错了 - 很简单,因为你有两个需要思考的问题(float ** x)。

确保你正在做: -

(*x)[0] = 0;
(*x)[1] = 100;
... etc...

...而不是

x[0] = 0; // compiles, but overwrites the pointer with NULL...

..或

*(x[0]) = 0;

..或

*x[0] = 0;

当你调用function_using_a_and_b时更改a和b - 这很奇怪。您 正确地按值传递它们。你在这里使用什么编译器?

答案 6 :(得分:0)

为什么malloc x不在main中,所以你不会忘记稍后释放x,从而造成内存泄漏。我建议避免使用浮动**,这太混乱了。

答案 7 :(得分:0)

嘿,好谜。 : - )

我的猜测是你的函数声明如下:

void fill_in_x(float* x);

应该时:

void fill_in_x(float** x);

使用你的声明,函数需要获得一个浮点指针,但你传递浮点指针x的地址 - 它就在堆栈的某个地方,因为这是局部变量所在的位置分配。

这意味着您在自己的调用堆栈上分配空间,结果显然可怕。 :)

答案 8 :(得分:0)

你可能正在使用

*x[0] = 3.0;

<{1>}中的

,当您确实需要使用

fill_in_x()

编辑:顺便说一句,C没有通过引用传递,它只是一个教学功能。您只需按值传递变量ADDRESSES,然后取消引用该值以获取原始变量。

答案 9 :(得分:0)

void fill_in_x(float** x, int num_vals)
{
    *x = (float*)malloc(num_vals * sizeof(float));

    for (int i = 0; i < num_vals; ++i) {
        (*x)[i] = (float)i;
    }
}

这也有效。让我想知道你的fill_in_x()是什么样的。代码没有任何问题。

答案 10 :(得分:0)

如最初编写的那样,调用范围时function_using_a_and_b()范围内没有原型,因此编译器必须在传递float之前将double值提升为{{1}}。然后该函数以原型notataion编写,因此编译器可能不会注意到函数已经被双精度调用,即使原型符号允许它传递浮点数。这会在打印时产生奇怪的值。

我不相信编译器不会发现问题 - 但它可能会说明你所看到的。当然,如果函数在单独的源文件中,那么编译器就没有机会发现不匹配。