Funzioni

di il
4 risposte

Funzioni

Salve ragazzi,
ho un'altra domandina da farvi. Sto cercando di farmi delle funzioni generali di ottimizzazione (cioè le prendo da sorgenti affidabili) e ho il seguente problema. Solitamente in una routine di ottimizzazione quello che cambia di volta in volta è la funzione da ottimizzare e il mio problema è rendere la funzione di ottimizzazione "il più flessibile possibile" in modo tale che l'utente non debba mettere mano dentro la funzione di ottimizzazione, ma scriva solamente la propria funzione da ottimizzare secondo alcune piccole regole. Ecco l'esempio:


struct opt_args{
	double *data;
	int length_data;
}; 

static double parabola(double x, struct opt_args *args)
{
	int i;
	double res;
	for(i=0;i<args->length_data;i++)
	 {
		res+= args->data[i]*pow(x,2)-2;
	 }	
	return(res);
}

double Bustra_R_zeroin(			/* An estimate of the root */
    double *ax1,			/* Left border | of the range	*/
    double *bx1,			/* Right border| the root is seeked*/
    double *Tol,			/* Acceptable tolerance		*/
    int *Maxit,				/* Max # of iterations */
    double (*f)(double, struct opt_args *args),/* Function under investigation	*/
    struct opt_args *args		/* Other arguments for f*/
		       )

{
.....
.....
    fa = (*f)(a, args);  
    fb = (*f)(b, args);
.....
....
}

come vedete la funzione da ottimizzare deve avere come primo argomento l'argomento rispetto al quale ottimizzare e per il resto degli argomenti l'utente dovrebbe definire una opportuna struttura.
Ora il mio problema è dichiarare in "parabola" che il secondo argomento è un puntatore a struttura opt_args e in "Bustra_R_zeroin" che l'ultimo argomento è un puntatore a struttura opt_args (e che la funzione puntata ha come secondo argomento un puntatore a struttura). La mia domanda è: è possibile dichiarare dei generici puntatori a struttura in modo tale che la funzione "Bustra_R_zeroin" non debba essere sempre modificata? Quel che so è che non è possibile usare una struttura (in senso lato) se non si è prima dichiarata, ma non so se questo implica che il mio problema non abbia soluzione.
Oppure, c'è una soluzione meno barabara al problema?

4 Risposte

  • Re: Funzioni

    Risolvi con void *args però nella funzione wrapper devi castare di nuovo a struct opt_args *. Il problema è che così violi il type system del C. Un void* può puntare a qualsiasi indirizzo (tranne puntatori a funzioni), quindi alla tua funzione è possibile passare praticamente tutto e il compilatore non fa una piega. I dolori si vedono solo a run time.
  • Re: Funzioni

    Ho appena provato! ho fatto questo
    
    struct opt_args{
    	double *data;
    	int length_data;
    }; 
    
    
    static double parabola(double x, void *arg_pointer ) 
    {
    
       int i;
       double res=0.0;
       struct opt_args *args = arg_pointer;  
    
       for(i=0;i<args->length_data;i++)
        {
          res+= args->data[i]*pow(x,2)-2.0;
        }   
       return(res);
    }
    
    
    double Bustra_R_zeroin(			/* An estimate of the root */
        double *ax1,			/* Left border | of the range	*/
        double *bx1,			/* Right border| the root is seeked*/
        double *Tol,			/* Acceptable tolerance		*/
        int *Maxit,				/* Max # of iterations */
        double (*f)(double, void *args),/* Function under investigation	*/
        void *args		/* Other arguments for f*/
    		       )
    
    {
    ...
    }
    
    tipo che dolori potrei avere?(infatti non ho mai considerato i puntatori void perchè sempre sconsigliati) ho fatto girare e va tutto che è una meraviglia.
  • Re: Funzioni

    Che il programma vada in crash se passi un argomento sbagliato, questi sono i dolori. Un void* è sconsigliato appunto perché perde le informazioni sul tipo di dato reale a cui punta. Dev'essere il programmatore (e chi scrive la documentazione) a prendersi la responsabilità di fare un cast corretto al tipo di dato reale.
    Se la tua funzione è compilata e messa in una libreria, io ci posso passare anche un puntatore a int o NULL. Il programma compila ma a run time s'inchioda.
    Insomma, il void* consideralo come un cerino acceso in mano a cui prestare attenzione per non bruciarti le dita.
  • Re: Funzioni

    Ok! grazie mille! Sinceramente mi rincuora sapere che le conseguenze "sono solo queste".ho capito moolto bene la questione. Mi sarebbe piaciuto usare va_start,_arg ecc ma da quel che ho capito non è molto agevole, e anzi mi è sembrato impossibile, maneggiare vettori/puntatori.
Devi accedere o registrarti per scrivere nel forum
4 risposte