Stavolta non sono d'accordo. Qualsaisi compilatore serio alloca spazio per la variabile di destinazione, dove va a mettere i risultati, non viceversa.
So' niubbo d'arduino, ma compilavo in C in tempi che sicuro te non eri ancora nato
ma stai scherzando? TUTTI i linguaggi che conosco soffrono di overflow di variabile!
trovamene uno che non abbia questo problema, non dico che sia impossibile ma molto, molto difficile.
Altrimenti mi spieghi che differenza c'è tra dichiarare un int o un long o un byte?
lesto:
ma stai scherzando? TUTTI i linguaggi che conosco soffrono di overflow di variabile!
trovamene uno che non abbia questo problema, non dico che sia impossibile ma molto, molto difficile.
Altrimenti mi spieghi che differenza c'è tra dichiarare un int o un long o un byte?
e tra un float e un double?
No, no, aspetta, non fraintendere.
Un conto e' l'overflow e un conto e' l'allocazione di memoria.
In tutti i compilatori che ho usato, tanti, ma mille anni fa, il problema che ho riscontrato qui non esisteva. E spiego meglio:
Se alloco
byte a;
e poi ci vado a mettere dentro
a=300;
Ovvio che vado fuori, in overflow.
se alloco
byte a;
int b = 300;
va bene, ovviamente.
e' evidente che se scrivo questo:
byte a;
int b;
...
b= int(300);
Va ancora bene ma e' une ridondanza inutile, visto che in "b" ho allocato il giusto spazio e "a" e' allocata
Da qui, e' evidente che
byte a;
int b;
...
b= 300a;
dovrebbe essere giusto.
Ho capito che il compilatore di arduino non lo fa, pero' a questo punto si comporta in modo diverso
Perche' se e' giusto
b = int(300a);
Allora DEVE essere NECESSARIO e non opzionale anche
b=int(a);
ah, ok, ora ho capito quello che intendi, ma sia il C, che il C++, che java, che php che python.... e posso ancora andare avanti... non ragionano così.
d = c3600+ b60 +a;
vuol dire: prendi C (che è int) e moltiplicalo con 3600 (sempre int), il risultato sarà messo in un int, essendo int la variabile "più grossa" (fregandosene bellamente dell'overflow), etc... alla fine il risultato verrà convertito in un long
puoi forzare, per esempio, 3600 ad esere long scrivendo
3600L
quindi
d = c3600+ b60 +a;
vuol dire: prendi C (che è int) e moltiplicalo con 3600 (ora è long), il risultato sarà messo in un long, essendo long la variabile "più grossa" (fregandosene bellamente di eventuali overflow), etc.
lesto:
ah, ok, ora ho capito quello che intendi, ma sia il C, che il C++, che java, che php che python.... e posso ancora andare avanti... non ragionano così.
d = c3600+ b60 +a;
vuol dire: prendi C (che è int) e moltiplicalo con 3600 (sempre int), il risultato sarà messo in un int, essendo int la variabile "più grossa" (fregandosene bellamente dell'overflow), etc... alla fine il risultato verrà convertito in un long
puoi forzare, per esempio, 3600 ad esere long scrivendo
3600L
quindi
d = c3600+ b60 +a;
vuol dire: prendi C (che è int) e moltiplicalo con 3600 (ora è long), il risultato sarà messo in un long, essendo long la variabile "più grossa" (fregandosene bellamente di eventuali overflow), etc.
Buono a sapersi, non ci avevo mai pensato..... Sono quelle cose che ti fanno perdere ore di lavoro per una cavolata...
E' la conversione implicita dei tipi di dato.
I calcoli vengono eseguiti usando il tipo di dati più grande tra quelli dell'operazione, ma il risultato viene poi riconvertito nel tipo di dati della variabile di destinazione.
Sul terminale seriale apparirà scritto 208. Nessun errore da parte del compilatore, nessun comportamento strano da parte del micro. Semplicemente, del risultato vengono presi i primi 8 bit, quelli cioè che stanno in un tipo di dati byte, nonostante i calcoli siano eseguiti a 32 bit.
void setup() {
delay(2000);
Serial.begin(19200);
}
void loop() {
byte a = 200;
int b;
b=a*10;
Serial.println(b, DEC);
delay(2000);
}
A quello che ho capito l'operazione a * 10 viene eseguita a 8 bit, generando un overflow, e il risultato (sbagliato) viene messo in un int, giusto? Purtroppo ora non ho arduino per provare...
No, ottieni 2000.
Questo perché, come ti ho scritto, il compilatore fa sì che l'operazione venga eseguita usando il tipo di dati più grande necessario a contenere i valori in gioco e solo alla fine viene convertito il risultato per il tipo di dato in uso.
Ora, siccome 200*10 va oltre il tipo byte, il compilatore fa usare un int (16 bit), ottieni così 2000 che viene memorizzato in una variabile di tipo int. Siccome int in un int ci sta, non hai nessun "pezzo" perso per la strada.
leo72:
No, ottieni 2000.
Questo perché, come ti ho scritto, il compilatore fa sì che l'operazione venga eseguita usando il tipo di dati più grande necessario a contenere i valori in gioco e solo alla fine viene convertito il risultato per il tipo di dato in uso.
Ora, siccome 200*10 va oltre il tipo byte, il compilatore fa usare un int (16 bit), ottieni così 2000 che viene memorizzato in una variabile di tipo int. Siccome int in un int ci sta, non hai nessun "pezzo" perso per la strada.
lesto:
ah, ok, ora ho capito quello che intendi, ma sia il C, che il C++, che java, che php che python.... e posso ancora andare avanti... non ragionano così.
d = c3600+ b60 +a;
vuol dire: prendi C (che è int) e moltiplicalo con 3600 (sempre int), il risultato sarà messo in un int, essendo int la variabile "più grossa" (fregandosene bellamente dell'overflow), etc... alla fine il risultato verrà convertito in un long
puoi forzare, per esempio, 3600 ad esere long scrivendo
3600L
quindi
d = c3600+ b60 +a;
vuol dire: prendi C (che è int) e moltiplicalo con 3600 (ora è long), il risultato sarà messo in un long, essendo long la variabile "più grossa" (fregandosene bellamente di eventuali overflow), etc.
leo72:
No, ottieni 2000.
Questo perché, come ti ho scritto, il compilatore fa sì che l'operazione venga eseguita usando il tipo di dati più grande necessario a contenere i valori in gioco e solo alla fine viene convertito il risultato per il tipo di dato in uso.
Ora, siccome 200*10 va oltre il tipo byte, il compilatore fa usare un int (16 bit), ottieni così 2000 che viene memorizzato in una variabile di tipo int. Siccome int in un int ci sta, non hai nessun "pezzo" perso per la strada.
no. concordo sul risultato ma non sul motivo.
scrivere "a10" da per implicito che 10 sia un int, quindi:
int b=a10;
sarà 2000
se fai
a = a*10;
l'operazione darà 2000 (perchè 10 è un int), ma poi verrà troncata in byte
prova a fare uno skect di esempio:
2000 trocanto in byte credo sia 0 (caso a = a10;)
se invece fai
byte b=10;
byte a=200;
a=ab; //in modo che entrambi i membri siano forzatatmente in binario
dovresti trovare un risultato diverso, credo (dovrei fare i conti)
1500035000=525000000, che è un numero a 28 bit. Eppure il terminale stampa ancora un valore coretto.
64
Che è appunto 525000000&255 (ossia i primi 8 bit) del numero.
Se invece provi con
a=150000350000;
otterrai 0.
questo perché il risultato non può essere contenuto in 32 bit, il tipo di dati più grandi gestibile dall'Atmega e va in overflow, dando come risultato 0. Quindi l'overflow viene ignorato (o per meglio dire non si verifica) solo finché il risultato è contenibile in un dato gestibile dal micro.
non vorrei che il precompilatore ci metta le mani. Prova a mettere il 15000 e/o il 35000 in variabili int. Anzi il 35000 non ci sta in un int, quindi (sempre il precompilatore) potrebbe aggiungere una bella L o una unsigned di soppiatto!
15000*35000=525000000, che è un numero a 28 bit. Eppure il terminale stampa ancora un valore coretto.
64
Che è appunto 525000000&255 (ossia i primi 8 bit) del numero.
se così fosse, ovvero avviene un cast implicito a long, allora ho sbagliato io. Ma non mi spiegherei più perchè il suo programma dà l'verflow a 32000 circa, il limte degli int (vedi sopra la mia possibile spiegazione)
Se invece provi con
a=150000*350000;
otterrai 0.
questo è quello che mi aspetterei di vedere (credo, non ho fatto i conti, e arduino è al momento impegnato)