PDA

View Full Version : [C] variabile modificata da funzione


frank10
16-09-2010, 10:44
Sono nuovo del C, forse questa è una banalità, portate pazienza.

Ho una variabile globale che cambia all'interno di una funzione.

Da un'altra funzione, voglio leggere quel valore, ma me ne dà un altro:

ad esempio, semplificando:


#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <windows.h>

void CalcolaConsumi( float );
void LeggiCounter();

float TimeAnow=0;
struct timeb tempo;


int main(short argc, char **argv)
{
int goLoop = 1;
int timer = atoi(argv[1]);
while (goLoop)
{

LeggiCounter();
CalcolaConsumi( TimeAnow);

Sleep( timer );
}


}

void LeggiCounter()
{
ftime(&tempo);
TimeAnow = (float)tempo.time*1000+tempo.millitm;

printf("%.0f\n", TimeAnow);
}


void CalcolaConsumi(float prova)
{

printf("%.0f\n", prova);
}


mi dà TimeAnow=
1284629672649 (che è corretto)
1284629725184 (da CalcolaConsumi mi dà sempre questo valore fisso)

Come mai, non è una variabile globale?

frank10
16-09-2010, 12:42
Ho scoperto che mettendo un altro printf all'interno della prima funzione LeggiCounter, dove cambia il valore della variabile, mi dà anche lì il risultato sbagliato.


void LeggiCounter()
{
ftime(&tempo);
TimeAnow = (float)tempo.time*1000+tempo.millitm;

printf("%.0f\n", TimeAnow); // CORRETTO

printf("%.0f\n", TimeAnow); // SBAGLIATO
}

Allora non c'entra il passaggio ad un'altra funzione, ma la funzione printf che mi modifica la variabile.

Come mai printf mi modifica la variabile appena creata?

frank10
16-09-2010, 13:30
Altra scoperta:

Aggiungendo uno Sleep(100); dopo la modifica della variabile, essa rimarrà sempre a un valore fisso anche alle successive chiamate! Non sarà più corretta!

void LeggiCounter()
{
ftime(&tempo);
TimeAnow = (float)tempo.time*1000+tempo.millitm;

Sleep(100);
printf("%.0f\n", TimeAnow);
printf("%.0f\n", TimeAnow);

}

A questo punto, non è neppure printf...
Ma cosa??

tuccio`
16-09-2010, 13:56
visto che non ha molto senso l'errore, probabilmente è un overflow, d'altronde non capisco perché usare il tipo float per valori interi positivi, per me con unsigned int funzionerà tutto :E

ps: che bruttezza tutte quelle variabili globali

frank10
16-09-2010, 14:19
Avevo usato float perché, essendo in ms, poi dividevo per 1000 per avere i secondi e devo sottrarre un altro valore per vedere la differenza e lì mi serve la virgola per avere un po' di corretta approssimazione.

Comunque sì, ho provato a mettere int e funziona.

Con int e i secondi non riuscirei ad avere abbastanza precisione.
Allora ho lasciato la lettura del tempo in ms in int e poi successivamente ho convertito in float per avere i secondi con la virgola.

Ottimo, grazie.


Bè, nell'esempio, ne ho messa solo una... dato che timeb è dentro un include.
Tu come faresti avendo parecchie variabili da aggiornare?
Passarle tutte tra funzioni con i return?

tuccio`
16-09-2010, 14:26
o passaggio per riferimento..

comunque TimeAnow e tempo sono due variabili globali, che intendi per "è dentro un include"?

in generale, comunque, evitare le variabili globali è una regola di buona programmazione

ps: comunque se ritieni corretta la scelta di usare una variabile in virgola mobile, c'è sempre il tipo double

frank10
16-09-2010, 22:32
Ho provato con double e funziona bene.
Quindi è solo il float a dare quei problemi. Strano.


Ho letto un po' sui puntatori (non li avevo fatti prima).

Quindi, togliendo le var globali, passare per riferimento, sarebbe ad esempio:



void LeggiCounter(double *pTime);
void CalcolaConsumi(double *prova);

int main(short argc, char **argv)
{
double TimeAnow=0;
int goLoop = 1;
int timer = atoi(argv[1]);
while (goLoop)
{
LeggiCounter(&TimeAnow );
printf("%f___\n", TimeAnow);
CalcolaConsumi( &TimeAnow );

Sleep( timer );
}

}


void LeggiCounter(double *pTime)
{
struct timeb tempo;

ftime(&tempo);
*pTime = (double)tempo.time*1000+tempo.millitm;
printf("%f\n", *pTime);

}

void CalcolaConsumi(double *prova)
{
printf("%f\n",*prova);
}

tuccio`
17-09-2010, 00:09
il passaggio per riferimento è bene farlo dove è richiesta la modifica... la funzione


void CalcolaConsumi(double *prova)
{
printf("%f\n",*prova);
}


non modifica il valore della variabile, e questo dovrebbe trasparire dall'intestazione della funzione.. un'intestazione del tipo


void CalcolaConsumi(double prova);


oppure



void CalcolaConsumi(const double *prova);


"dice" che la variabile non verrà modificata (perché non puoi farlo nella funzione)

in questo caso il passaggio per valore è la cosa migliore