【问题标题】:Returning double * in function argument在函数参数中返回双 *
【发布时间】:2015-09-23 23:34:52
【问题描述】:

无数 GSL 函数在其第一个参数中将其结果作为指针返回。比如

int gsl_matrix_get_col (gsl_vector * v, const gsl_matrix * m, size_t j)

我的编程水平非常低,但有人告诉我这样的事情对于局部变量是不可能的(在函数末尾删除),但对于指针是可能的,只要它们由调用函数正确声明和分配。我觉得很奇怪,指针和普通变量之间应该存在这样的根本区别,但是我尝试将这种结果存储在变量中用于一个简单的 GSL 程序,我想要一个函数 (fetch_eigenvalue() ) 输出两件事。而我失败了。我的程序如下:

#include <math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>


/* Parameters */
#define N 3


int CREATE_MATRIX_AND_VECTOR(gsl_matrix *m, gsl_vector *v);
double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos);

int main()
{
gsl_matrix *unit_matrix = gsl_matrix_calloc(N, N); //soon to be unity 
gsl_vector *v = gsl_vector_calloc(N);          //soon to be unit x vector
double *outcos = (double*)malloc(sizeof(double) );

printf("**********************************************\n");
CREATE_MATRIX_AND_VECTOR(unit_matrix, v);
fetch_eigenvalue(unit_matrix, v, outcos);   
printf("==IN MAIN: outcos = %e\n", *outcos);

free((void *)outcos);
gsl_vector_free(v);
gsl_matrix_free(unit_matrix);
printf("**********************************************\n");
return(0);
}

int CREATE_MATRIX_AND_VECTOR(gsl_matrix * m, gsl_vector *v)
{
int i;

    for (i = 0; i < N; i++)
    {
        gsl_matrix_set(m, i, i, 1.0);
    }

    gsl_vector_set(v, 0, 1.0);

return(0);
}

double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos)   //fetches eigenvalue, if Mv is parallel to v within accuracy gvaccu
                                    //rescos is the cosine of the angle between Mv and v
{

int i,lv;
double v0, v1, cos;
double result;
double vnorm, pnorm;
double rdot;
lv = v->size;

double gvaccu = 1e-10;


            gsl_vector *prod = gsl_vector_calloc(lv);
            gsl_matrix_get_row(prod, M, 0);

            if(gsl_blas_dnrm2(prod)==0.0)
            {
                result = 0.0;
            }
            else
            {
                gsl_blas_dgemv( CblasNoTrans,1.0, M, v, 0.0, prod);
                gsl_blas_ddot(prod, v, &rdot);
                pnorm = gsl_blas_dnrm2(prod);
                vnorm = gsl_blas_dnrm2(v);
                cos = rdot/pnorm/vnorm;
                cos = fabs(cos);
                rescos = &cos;

                if(fabs(cos -1.0) > gvaccu)
                {
                    result = -1.0;
                }
                else
                {
                v0 = gsl_vector_get(v,0);
                v1 = gsl_vector_get(prod,0);
                result = v1/v0;
                }
            }
        printf("==IN FETCH_EV: COS = %e\n", cos);//print cheat!!
        printf("==IN FETCH_EV: RESCOS = %e\n", *rescos);//print cheat!!
gsl_vector_free(prod);
return(result);     
}

我运行它并得到以下输出:

ludi@ludi-M17xR4:~/Desktop/Healpix_3.20$ g++ -o wrong_output wrong_output.c -L. -L/sw/lib -I/sw/include -lgsl -lblas && ./wrong_output 
**********************************************
==IN FETCH_EV: COS = 1.000000e+00
==IN FETCH_EV: RESCOS = 1.000000e+00
==IN MAIN: outcos = 0.000000e+00
**********************************************
ludi@ludi-M17xR4:~/Desktop/Healpix_3.20$ 

因此,调用者 main() 对 fetch_eigenvalue() 内部发生的事情一无所知,尽管我使用了指针。我究竟做错了什么?我有一种感觉,我误解了一些非常重要的东西。

【问题讨论】:

  • 顺便说一句,您不必显式分配一些东西来获取变量指针。例如,您可以声明double outcos; 并使用&amp;outcos 调用传递其指针的函数。类似this.

标签: c++ gsl


【解决方案1】:

我总结了您在fetch_eigenvalue 函数中使用参数rescos 所做的事情:

double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos)
{
    double cos;
    // some code
    rescos = &cos;
    // some code
    return(result);
}

在这里,您不是在修改 rescos 指向的双精度值,而是在修改变量 rescos 本身,它是您的 main 中使用的变量 outcos 的副本。

你想要在fetch_eigenvalue中做的是将cos的值复制到rescos指向的变量中:

double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos)
{
    double cos;
    // some code
    *rescos = cos;
    // some code
    return(result);
}

编辑:正如其他答案所述,最好尽可能避免使用 malloc,在这里您可以:

double outcos;
fetch_eigenvalue(unit_matrix, v, &outcos);

【讨论】:

    【解决方案2】:

    我怀疑这是因为rescos = &amp;cos; 语句将局部变量cos 的地址保存到rescos 中。但是,此变量的范围只是局部的,因此您不能在 main() 中使用它。我想你想做的是:

    1. fetch_eigenvalue函数中的rescos = &amp;cos;改成*rescos = cos;,这样cos的值就存放在rescos指向的地址了

    2. main()函数中仅使用double outcos;,即不要使用指针

    3. fetch_eigenvalue 称为fetch_eigenvalue(unit_matrix, v, &amp;outcos);

    【讨论】:

      【解决方案3】:

      我对 GSL 一无所知,但它似乎是一个使用 C 风格界面的库。要从函数中设置值,它们使用指针。您似乎还不知道如何使用这样的 API,所以这里有一些提示。

      声明

      double *outcos = (double*)malloc(sizeof(double) );
      ...
      fetch_eigenvalue(unit_matrix, v, outcos);   
      

      不是您希望使用这样的 API 的方式。相反,您只需定义一个双精度变量,并在调用中使用运算符的地址:

      double outcos;
      ...
      fetch_eigenvalue(unit_matrix, v, &outcos);   
      

      另外,在您的方法中,要分配一个值,请使用不要使用

              cos = fabs(cos);
              rescos = &cos;
      

      但是

              cos = fabs(cos);
              *rescos = cos;
      

      将值分配给指向的变量,而不是指针。 希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2013-10-03
        • 2013-04-30
        • 2020-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-27
        • 2021-10-29
        • 2019-12-01
        相关资源
        最近更新 更多