Newsgroup: it.comp.lang.c
Titolo: una MACRO

Ciao... sto bazzicando con un sogente per una funzione di HASCING...
e, compilandola, ottengo una serie di messaggi di warning ed alla fine
non viene compilato nulla. L'errore (sono tanti, tutti uguali, perche'
compare
piu' volte lo stesso codice) e' il seguente:
[C++Warning] md5.c(252): Ambiguous operators need parentheses.
Ho notato che il problema sta in una macro:
#define MD5STEP(f, w, x, y, z, data, s) \
 ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
a cui seguono circa duecento sue utilizzazioni, come queste:
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
che provocano gli errori di ambiguita'.
Purtroppo non ho quasi mai usato le macro, e non riesco a capire dove
stia il problema.
Qualcuno mi puo' aiutare?
Grazie,
Alberto

 Alberto
La macro vengono esplose nel codice sorgente dal preprocessore e
puoi vedere il sorgente che risulta vacendo girare solo il detto
preprocessore. Non ho sotto mano la tabella delle priorita' degli
operatori, ma sospetto che gli shift di bits e l' operatore OR
BINARIO ( | ) abbiano la stessa priorita' e' il compilatore ti avverte
che potrebbe generare un codice per te non prevedibile.
Prova a seguire i "consigli" del compilatore e metti le parentesi
(che non pesano nulla) per stabilire l' ordine di valutazione:
.... ,w = (w<<s) | (w>>(32-s)), ....
L' operatore virgola dovreppe avere priorita' piu' bassa di tutti e
non dovrebbero essere necessarie parentesi.
Ciao.


Prova con:
#define MD5STEP(f, w, x, y, z, data, s) \
        ( w += f(x, y, z) + data,  w = (w<<s | w>>(32-s)), w += x )
Raffaele.

  ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
Prova a mettere le parentesi
( w += f(x, y, z) + data,  w = (w<<s) | (w>>(32-s)),  w += x )
e, se ancora non va
( w += f(x, y, z) + data,  w = ((w<<s) | (w>>(32-s))),  w += x )
EMG

che potrebbe generare un codice per te non prevedibile.
Più che di codice imprevedibile (il codice prodotto, in virtù della
associatività degli operatori, è lo stesso), si parla di possibile
distrazione del programmatore dal capire bene cosa vuole fare.
La giusta riscrittura di 
w = w<<s | w>>32-s
è 
w = (w) << (s) | ((w) >> (32-(s))) 
Sempre che sia questo ciò che il programmatore vuole fare e sempre che
l'associtività degli operatori tra bit (non la ricordo) sia da
sinistra a destra (la più probabile).
--
Andrea Laforgia        (
andrea_...@bigfoot.com
)

        ( w += f(x, y, z) + data,  w = (w<<s | w>>(32-s)), w += x )
L'ambiguità rimane : siamo sicuri che il programmatore voglia eseguire
prima w << s | w e poi porre questo valore come primo operando di >>
con 32-s ?
--
Andrea Laforgia        (
andrea_...@bigfoot.com
)

 w = (w) << (s) | ((w) >> (32-(s)))
Hai ragione. Un altro motivo per cui cerco di usare solo
macro semplici. Effettivamente w ed s essendo argomenti di
macro possono essere espressioni a loro volta e devono essere
chiuse tra parentesi. w inoltre deve essere un l-value.
Inizialmente avevo ragionato fuori da questo contesto,
ma l' espressione effettivamente esplosa nel codice potrebbe
anche diventare in certi punti del programma
* pint + 1 = * pint + 1 << i + 2 | + pint + 1 >> (32 - (i + 2))
chiudere ogni argomento di macro tra parentesi E USARLO UNA SOLA
VOLTA dovrebbero divenire regole da non trasgredire mai.
grazie e ciao.

 con 32-s ?
Come hai detto giustamente tu nell'altro post non c'è ambiguità, perchè le
operazioni avvengono in questo ordine:
1) w<<s
2) w>>(32-s)
3) w<<s | w>>(32-s)
e il valore ottenuto viene posto uguale a w.
(NB nei primi due passi il valore di w è lo stesso)
Io pensavo che ci volessero le parentesi per via della precedenza
dell'uguale con l'OR :( e invece è abbastanza chiaro che non è così :)
Comunque questa operazione si chiama "left circular shift" e serve per
prendere s bit a sinistra di un numero a 32 bit e metterli a destra. E'
una cosa abbastanza usata nelle funzioni di HASH, queste funzioni sono
pensate per avere un output non riconducibile all'input (funzioni non
invertibili)
Raffaele.

e il valore ottenuto viene posto uguale a w.
No, aspetta, nel caso di w = ( w << s | w >> (32-s) ) è probabile che
si continui a sbagliare.
Stando così le cose, l'ordine delle operazioni è il seguente :
((w << s ) | w ) >> (32-s))
Che non è, evidentemente, ciò che si vuole fare.
--
Andrea Laforgia        (
andrea_...@bigfoot.com
)

 Che non è, evidentemente, ciò che si vuole fare.
Ma se non sbaglio la precedenza degli operatori mette lo "shift" prima
dell'"OR" e quindi non ci dovrebbe essere ambiguità.
Raffaele.

dell'"OR" e quindi non ci dovrebbe essere ambiguità.
Nonricordo la precedenza degli operatori e, comunque, e' buona regola,
in queste situazioni, porre sempre delle parentesi (per sicurezza) in
quanto bisogna tener presente che se anche chi scrive un programma ha
ben chiara la precedenza, chi lo andra' a leggere potra' non
ricordarsela.
--
Andrea Laforgia        (
andrea_...@bigfoot.com
)