A proposito degli UL

Ciao a tutti

Nel magnetometro, per fare delle prove, ho forzato sum e sumsq con dei valori fissi e ho notato una cosa che non riesco a spiegarmi:

uint32_t sumsq=0;
sumsq=900*900*2000UL; // NON FUNZIONA!
sumsq=900UL*900*2000; // Funziona.
sumsq=(UL)900*900*2000 // ERRORE!
sumsq=(uint32_t)900*900*2000 // Funziona.

Perché? Perché lo legge solo dopo che ha già fatto le prime due moltiplicazioni?... :frowning:

Perché le espressioni le valuta da sinistra a destra.
Intanto "(UL)" è proprio errato, non compila neanche perché non è un tipo ma solo un indicatore per il compilatore per gestire correttamente il valore costante che lo precede. Quindi non "UL" ma "uint32_t" (o "unsigned long").
Poi la prima moltiplicazione lui la fa tra interi, e 900*900, che farebbe 810.000, viene calcolato su uint16 quindi va in overflow restituendo 23.568, che moltiplicato per l'unsigned long 2.000 dà 47.136.000.
Nella seconda e nell'ultima parte già come unsigned long o uint32_t, quindi effettua correttamente tutti i passaggi come unsigned long.

EDIT: nota che il cast dell'ultima espressione si applica solo al primo valore, ossia diciamo che equivale a:

sumsq=((uint32_t)(900)) *900*2000; 

e non a:

sumsq=(uint32_t)(900*900*2000); 

che dà un risultato ancora peggiore (15.616) :wink:

...poiché fa la moltiplicazione in un int16 e poi fa un inutile casting a uint32?

Esatto. Con o senza quel cast, il risultato non cambia anche perché quel cast è addirittura inutile perché automatico quando assegni un valore di un tipo, anche se ottenuto da una espressione, ad una variabile di un altro tipo.

Purtroppo sono cose non molto "visibili" ma le capisci solo quando ci "sbatti la faccia" (io l'ho imparato proprio così :wink: ).

Grazie, docdoc! :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.