在函数参数中返回双 *
Returning double * in function argument
无数 GSL 函数 return 它们的结果作为第一个参数中的指针。例如
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() 内部发生的事情一无所知,尽管我使用了一个指针。我究竟做错了什么?我有一种感觉,我误解了一些非常重要的东西。
我总结了您在 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
本身,它是你的变量 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);
我怀疑这是因为语句rescos = &cos;
将局部变量cos
的地址存入了rescos
。但是,这个变量的范围只是局部的,所以你不能在 main()
中使用它。我想你想做的是:
将fetch_eigenvalue
函数中的rescos = &cos;
改为*rescos = cos;
,使cos
的值存放在[=指向的地址11=]
在main()
函数中仅使用double outcos;
,即不使用指针
- 将
fetch_eigenvalue
称为 fetch_eigenvalue(unit_matrix, v, &outcos);
我对 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;
将值赋给指向的变量,而不是指针。
希望这有帮助。
无数 GSL 函数 return 它们的结果作为第一个参数中的指针。例如
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() 内部发生的事情一无所知,尽管我使用了一个指针。我究竟做错了什么?我有一种感觉,我误解了一些非常重要的东西。
我总结了您在 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
本身,它是你的变量 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);
我怀疑这是因为语句rescos = &cos;
将局部变量cos
的地址存入了rescos
。但是,这个变量的范围只是局部的,所以你不能在 main()
中使用它。我想你想做的是:
将
fetch_eigenvalue
函数中的rescos = &cos;
改为*rescos = cos;
,使cos
的值存放在[=指向的地址11=]在
main()
函数中仅使用double outcos;
,即不使用指针- 将
fetch_eigenvalue
称为fetch_eigenvalue(unit_matrix, v, &outcos);
我对 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;
将值赋给指向的变量,而不是指针。 希望这有帮助。