Newsgroup: it.comp.lang.c
Titolo: promozione intera

salve,
il mio obiettivo è calcolare il quadrato di un valore ad 8 bit: uint8_t
var8u;
Ecco la possibile maniera per farlo, nel caso  var8u=32:
uint8_t var8u=32; //var8u=2^5
uint16_t var16u=var8u*var8u;
ora io ritengo che questa maniera di scrivere il codice non dia lo stesso
risultato su
architetture diverse. In particolare il risultato dipende da sizeof(int)
sull'architettura
considerata.
Ecco il mio ragionamento:
a)se sizeof(int)=4
quando il C calcola: var8u*var8u, esegue la promozione intera (gli ingressi
dell'operando "*"
passano da 8 bit a 32 bit). Qui ndi esegue il calcolo con gli ingressi a 32
bit. L'esito
dell'operazione viene tenuto memorizzato in 32 bit.
I 16 bit meno significativi di questo valore a 32 bit, vengono assegnati
alla variabile var16u
(avviene il troncamento).
Poichè l'esito di (8bit)^2 in 16 bit ci sta sempre, allora io ottengo il
risultato corretto.
Infatti sul mio computer, ove sizeof(int)=4, ottengo il risultato corretto.
b)se sizeof(int)=2
Questo caso è analogo al precedente.
Si ottiene il valore corretto in ogni caso.
c)se sizeof(int)=1 (il che potrebbe accadere nei microcontrollori ad 8 bit)
quando il C calcola: var8u*var8u, gli ingressi sono già int e pertanto dire
che avvenga o meno
la promozione intera non cambia niente (gli ingressi dell'operando "*"
permangono ad 8 bit).
Quindi esegue il calcolo con gli ingressi a 8 bit. L'esito
dell'operazione viene tenuto memorizzato in 8 bit (ciò comporta la perdita
di informazione degli
8 bit più significativi).
Quando questi 8 bit bit meno significativi vengono assegnati alla variabile
a 16 bit, ormai il
danno è fatto, ed è irrecuperabile.
La variabile var16u conterrà il risultato errato (essendo var8u>=16).
E'corretto fin qui?
Ne consegue che la precedente istruzione, sia pur trasportabile, dà esiti
diversi in architetture
diverse.
Come è possibile ottenere l'esito corretto in ogni caso?
Secondo me si dovrebbe scrivere così:
uint8_t var8u=32; //var8u=2^5
uint16_t var16u=(uint16_t)var8u*var8u;
Così sono sicuro di ottenere il risultato corretto.
ora però analizziamo ciò che avvenga in questo caso su un microcontrollore
ad 8 bit (che sappia
 eseguire le moltiplicazioni con gli ingressi ad 8 bit e l'esito a 16 bit
posto in una coppia di
 registri)dove valga:
sizeof(int)=1
1)nell'eseguire il cast, si aggiunge 1 byte di zeri a precedere il byte
della variabile var8u.
Così ottengo due byte: il byte più significtivo A ed il  byte meno
significativo B.
2)anche l'altro fattore viene concepito a 2 byte, identico a quello già
creato,
perchè il fattore rimasto ad 8 bit(senza il cast) viene anche esso
convertito in 2 byte.
3)viene eseguita la moltiplicazione fra i due fattori.
In teoria, sapendo come siano stati ricavati i due fattori a 2 byte, a
partire dalle variabili ad
1 byte, si sa già a priori
che basta eseguire solo 1 istruzione di moltiplicazione monobyte: "B*B".
Ma il compilatore C lo capisce da solo?
Oppure esso è talmente inefficiente da eseguire sia A*A che A*B che B*A che
B*B, e da sommare i
loro risultati, opportunamente shiftate del n° opportuno di byte?
Sapere ciò è rilevante, quando si vuole implementare un codice in maniera
efficiente su un
microcontrollore.
Grazie,
adriano

 c)se sizeof(int)=1 (il che potrebbe accadere nei microcontrollori ad 8 bit)
No, credo che puoi sempre assumere sizeof(int)>=2.
E.

No, credo che puoi sempre assumere sizeof(int)>=2.
Hummm no. Dovrebbe essere:
1 = sizeof(char) <= sizeof(int)

Andrea Laforgia ha scritto:

Su
 
http://en.wikipedia.org/wiki/Integer_(computer_science)
sembra dire che il minimo per int č 2. Guarda la nota sotto la tabella.
E.

 microcontrollore.
Fondamentalmente devi sapere come funziona la ALU del microcontrollore.
Il micro potrebbe avere memoria e bus a 8bit, ma avere dei registri interni 
a 16bit.
Potrebbe gestire in hardware operazioni sui 16bit.
Normalmente se programmi in C tutta sta menata di come il micro fa i 
calcoli la dimentichi e lasci fare al compilatore.
Se invece programmi in assembler allora il modo in cui programmi dipende 
anche dall'architettura del micro.
Ciao Jack
-- 
Eroi non si nasce, ti incastrano
- Jim Belushi

sembra dire che il minimo per int č 2. Guarda la nota sotto la tabella.
Fa un discorso generale non specificamente rivolto al C e dice che
"usually" la lunghezza in bit č multipla di 2. Che io sappia, nulla
vieta in C che un int sia lungo 1 byte.

 vieta in C che un int sia lungo 1 byte.
Solo se quel byte puo' rappresentare i valori tra INT_MIN e INT_MAX
completamente, e INT_MAX e' garantito dallo standard avere un valore
minimo di 32767.
Quindi un byte del genere dovrebbe avere almeno 16 bit.
Una implementazione dello C che ha int che non puo' rappresentare quei
valori non e' un'implementazione conformante.

 Quindi un byte del genere dovrebbe avere almeno 16 bit.
Sě, bisogna sempre distinguere il byte dallA sua lunghezza in bit.
Formalmente, come dicevo, nulla vieta che sizeof(int) = 1, poi bisogna
vedere quanto č lungo il byte. Ora come ora non conosco piattaforme che
prevedano il byte da 16 bit, per cui credo che sia molto piů frequente
trovare sizeof(int) = 2. In linea di principio, perň, questo vincolo
specifico non dovrebbe esistere.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it