2013-04-04 6 views

risposta

30

Se si dovesse implementare un compilatore, cosa faresti? Effettivamente, sceglieresti l'implementazione più veloce per entrambi. Poiché entrambi sono uguali, questa implementazione più veloce è la stessa per entrambi.

In altre parole, qualsiasi compilatore rilasciato dopo 5000 B.C. genererà lo stesso codice assembly per entrambi x = 0 e x ^= x se si abilitano le ottimizzazioni. Ciò significa che sono ugualmente veloci.

Questo non va solo per assegnazione/xorring, ma anche per multiplication, tra gli altri algoritmi. Esprimi il tuo intento e lascia che il compilatore lo ottimizzi. Il compilatore è più ottimizzato di te, fidati di me.

In altre parole, scrivere codice leggibile e utilizzare x = 0;.


Oh, e dal modo in cui, bit a bit xorring un intero non inizializzato per sé è un comportamento indefinito e un buon compilatore dovrebbe ottimizzare l'intera cosa.

+11

L'ho upvoted, anche se la domanda era su C e non su COBOL: D – StoryTeller

11

Prima di tutto, se alla variabile non è stato assegnato un valore, è tecnicamente un "comportamento non definito" fare qualcosa di diverso dall'assegnare un valore ad esso.

In secondo luogo, XOR con se stesso è improbabile che sia più veloce su un processore prodotto negli ultimi 15-20 anni, poiché richiede una lettura aggiuntiva. Potrebbe essere stato più veloce (a causa del fatto che è SHORTER CODE) molto tempo fa, ma in realtà, credo che anche questo sia falso.

Modifica: Vorrei sottolineare che potrebbe essere ancora più veloce/più compatto per XOR un registro per renderlo zero nei processori moderni. Ma se supponiamo che non possiamo sapere se x è in un registro o meno, allora non dovremmo rendere più complicato per il compilatore determinare cosa stiamo effettivamente facendo.

+4

In realtà, creare un registro con se stesso è il modo standard e più veloce per azzerare esso. L'hardware moderno lo considera un caso speciale per evitare la dipendenza dalla lettura. Viene spesso risolto tramite la rinomina del registro con un pool di registri di zero. – Mysticial

+0

Mentre stavi scrivendo, stavo modificando la mia risposta ... –

+0

@Mysticial: Si noti che anche la CPU è abbastanza intelligente - ad esempio, non conosce solo 'xor rax, rax', ma anche 'sub rax, rax' quindi i due finiscono per eseguirsi in modo identico. –

2

Perché speculare su cosa fa il compilatore? Proviamo invece!

Ecco alcuni codice di prova:

void fzero() 
{ 
    unsigned long x; 

    x = 0; 
} 

void fxor() 
{ 
    unsigned long x; 

    x ^= x; 
} 


int main() 
{ 
    fzero(); 
    fxor(); 
} 

E adesso permette di guardare il codice macchina risultante:

; 10 : unsigned long x; 
; 11 : 
; 12 : x ^= x; 
; 13 : } 

00000 c2 00 00  ret  0 

; 3 : unsigned long x; 
; 4 : 
; 5 : x = 0; 
; 6 : } 

00000 c2 00 00  ret  0 

PUBLIC main 
; Function compile flags: /Ogtpy 
; COMDAT main 
_TEXT SEGMENT 
main PROC      ; COMDAT 

; 18 : fzero(); 
; 19 : fxor(); 
; 20 : } 

    00000 33 c0  xor  eax, eax 
    00002 c3  ret  0 
main ENDP 

Oh, guarda! Erano ugualmente veloci, entrambi prendendo esattamente 0 ns.