2015-09-23 8 views
0

Бесчисленные функции GSL возвращают их результат как указатель в свой первый аргумент. НапримерВозвращение double * в аргументе функции

INT gsl_matrix_get_col (gsl_vector * v, Const gsl_matrix * м, 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);  
} 

я запускаю его и получить следующий вывод:

[email protected]:~/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 
********************************************** 
[email protected]:~/Desktop/Healpix_3.20$ 

Таким образом, вызывающий абонент основной() ничего не знает о том, что произошло в fetch_eigenvalue(), Eventhough я использовал указатель. Что я делаю не так? У меня такое чувство, что я неправильно понял что-то очень важное.

+1

Кстати, вам не нужно явно выделять что-то, чтобы получить указатель переменной. Например, вы могли бы объявить «double outcos;» и вызвали функцию, передающую свой указатель, используя '& outcos'. Что-то вроде [this] (https://ideone.com/kPDYvO). – wendelbsilva

ответ

3

Я подытожить, что вы делаете с параметром rescos в вашей fetch_eigenvalue функции:

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); 
} 

EDIT: Как заявил другие ответы, это лучше избегать таНос, когда вы можете , и здесь вы можете:

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

Я подозреваю, что это потому, что оператор rescos = &cos; сохраняет в rescos адрес й e локальная переменная cos. Однако область действия этой переменной является локальной, поэтому вы не можете использовать ее в main(). Я предполагаю, что вы хотите сделать, это:

  1. изменения rescos = &cos; к *rescos = cos; в функции fetch_eigenvalue так, что значение cos хранится на адрес, на который указывает rescos

  2. использования только double outcos; в main() функция, то есть, не используйте указатель

  3. вызов fetch_eigenvalue в fetch_eigenvalue(unit_matrix, v, &outcos);
1

Я ничего не знаю о 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; 

присвоить значение переменной, на которую указывает указатель, а не указатель. Надеюсь, это поможет.

Смежные вопросы