2010-06-25 5 views
6

funzionalità SDK di Windows è riuscita macro:Perché tante parentesi nella macro SUCCEEDED?

#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) 
-----------------------^-------------^----- 

chiaramente come con altre macro Ci sono le parentesi per garantire il diritto all'interpretazione del intenti da parte del compilatore.

Quello che non capisco è perché ci sono parentesi intorno a (HRESULT)(hr) (li ho contrassegnati con il carattere ^). hr è tra parentesi in modo che possa esistere qualche costrutto complesso, HRESULT è tra parentesi per formare un cast in stile C, quindi l'intero costrutto >= è tra parentesi, quindi perché la coppia di parentesi in più intorno a (HRESULT)(hr)?

+0

Mi scuso per la modifica iper-pedantina, ma il titolo della domanda mi dava fastidio ogni volta che l'ho visto sulla pagina principale ... – AakashM

+0

@AakashM: Dato che non sono un madrelingua inglese, devo chiedere: che cos'è la differenza tra "parentesi" e "parentesi"? Vedo frasi come "è necessario rafforzare gli argomenti correttamente nella tua macro" ogni qua e là. Perché la parola "parentesi" non è adatta qui? – sharptooth

+1

@sharptooth: "parentesi" spesso, anche se non sempre, significa "{}", a volte chiamato "parentesi graffe". "Parentesi" di solito significa '()', a volte chiamato "parentesi tonde". "Brackets" è talvolta usato per significare '[]' o '<>', a volte chiamato "parentesi quadre" e "parentesi angolari". Tutti e tre i termini sono spesso usati in modo intercambiabile. L'inglese non è preciso come il C++. –

risposta

7

Lo standard C mette il cast ad una priorità più alta rispetto al confronto, quindi le parentesi non sono richiesto per il compilatore.

Tuttavia, le persone leggono la definizione della macro e inserendole rende esplicita la precedenza, in modo che sia ovvio per le persone che la leggono che è il risultato del confronto (HRESULT) hr) con zero anziché il risultato del confronto senza dover pensare alla precedenza.

2

Le parentesi graffe si assicurano che gli elementi siano presi nell'ordine corretto. Se non si desidera che il compilatore da fare:

  1. (hr) >= 0

  2. risultato convertito del 1. di HRESULT.

Invece si desidera convertire solo l'espressione (hr) a HRESULT, quindi confrontare che con 0.

+1

Certo, ma questo è ciò che la precedenza degli operatori C e C++ fa comunque, e la maggior parte delle persone lo comprende. –

1

È necessario assicurarsi che hr venga convertito in HRESULT prima di essere confrontato, invece di HRESULT (hr> = 0).

+2

Le regole di precedenza garantiscono che; le parentesi chiariscono al lettore che questo è il caso. –

0

Per assicurarsi che l'espressione che si espande da (h) è realizzata mediante fusione per HRESULT, e confrontati con 0.

5

Le parentesi aggiuntive non cambiano il significato, ma rendono esplicita la precedenza. Senza di loro, un lettore che non conoscesse tutte le regole di precedenza avrebbe dovuto capire cosa significasse l'espressione.

Per chiarire, mi riferisco solo alle parentesi intorno all'espressione cast, come indicato nella domanda. Gli altri sono necessari (a meno che la macro fosse intesa solo per C++ e non C, nel qual caso è possibile modificare lo (HRESULT)(hr) in HRESULT(hr)).

+0

-1, non vero. Vedere l'esempio nella mia risposta: il significato può cambiare in base agli argomenti passati, poiché le macro sono sostituzioni di testo jsut. – peterchen

+0

@peterchen: in questo caso, l'argomento è racchiuso tra parentesi, quindi il significato è lo stesso per qualsiasi espressione valida, con o senza parentesi extra attorno all'espressione cast. I macro possono sicuramente avere delle insidie, ma non questa. A meno che tu non sia in grado di fornire un esempio di un argomento che potrebbe infrangerlo. –

+0

Hai ragione, Mike, ho ignorato la "linea divertente" sotto il suo testo. Non è possibile revocare il -1 a meno che non si modifichi, però. – peterchen

3

Risposta breve: chissà cosa stavano pensando gli sviluppatori di MS. Tuttavia, le parentesi intorno a hr sono ovviamente necessarie poiché hr potrebbe essere un'espressione composta da più di un singolo operando. Le parentesi intorno ((HRESULT) (hr)) non sono necessarie per quanto posso vedere. Questo probabilmente è stato fatto solo per abitudine cautelativa: quando si lavora con il preprocessore, è meglio avere troppe parentesi che troppe poche.

3

Questo è per far fronte alle carenze macro - sono solo una sostituzione di testo!

immaginare le seguenti macro

#define DOUBLE(x) x*2 

int v = DOUBLE(1+1); // == 1+1*2 == 3. Did you expect 4? 

Così le regole del pollice per le macro sono:

  • li usano solo se non c'è altro modo per risolvere il tuo problema
  • avvolgere tutti i parametri in parantheses (per evitare il problema precedente)
  • avvolgere l'intera espressione in paranthes (per evitare altri problemi simili)
  • fare ogni parametro si verificano solo una volta (per evitare problemi con effetti collaterali)

Quindi, una macro migliore sarebbe:

#define DOPPIA (x) ((x) * 2)

Sei quasi arrivato, le rimanenti parate in te sono dovute al cast.


Così possiamo criticare due punti:

D: perché è una macro, non è una funzione inline?
A: Compatibilità con le versioni precedenti. C non ha funzioni inline (o almeno non lo ha fatto), l'uso di funzioni per le migliaia di dichiarazioni di questo tipo avrebbe causato la maggior parte dei compilatori di quel tempo.

Q: Le paraste necessarie sono davvero necessarie per questa macro specifica? A: Non so. Probabilmente mi ci vorrà mezz'ora o più per dimostrare formalmente (o rifiutare) che non ci sia alcun parametro sensibile e un ambiente di "chiamata" dove ciò abbia effetti indesiderati. Preferirei seguire le linee guida ragionevoli come menzionato sopra, e continuare a scrivere codice.

+0

Nel primo esempio manca la definizione di 'DOUBLE' ... –

+2

Questo è un buon consiglio generale, ma non è pertinente alla domanda; l'argomento di SUCCEEDED è racchiuso tra parentesi come dovrebbe essere, così come l'intera espressione. La domanda riguarda le parate superflue attorno all'espressione cast. –

+0

@Donal: eh? è la prima riga .. – peterchen

3

L'autore era semplicemente stupido. Tutte le parentesi extra (attorno al cast) sono più difficili da analizzare visivamente. Chiunque pensi che il paragone possa avere una precedenza più alta rispetto al casting, deve imparare le basi della lingua prima della codifica ... per non parlare del buon senso.