2017-01-18 2 views
2

Ist es schneller zu überspringen if Aussage, wenn die Aussage wahr ist? Zum Beispiel:Ist es schneller zu goto zu überspringen, wenn Anweisung

if (a = true) { 
    blah blah... 
    goto end; 
} else { 
    blah blah.. 
} 

label: end; 

Wäre dieser Code schneller als:

if (a = true) { 
    blah blah... 
} else { 
    blah blah.. 
} 
+8

nein, tun das nicht – yano

+4

überhaupt keinen Sinn macht. – AnT

+1

der Compiler würde automatisch Code generieren, um nach dem else Teil zu verzweigen. Außerdem sollten Sie sagen: if (a) ' – bruceg

Antwort

6

sein Ich wäre überrascht, wenn jeder anständiger Compiler nicht den gleichen Assembler für diese beiden Möglichkeiten emittieren hat. Hier ist ein einfaches C-Programm, das kompiliert und läuft:

#include <stdio.h> 

int main(void) 
{ 
    int c = getchar(); 

    if (c == 'y') { 
     ++c; 
     goto end; 
    } else { 
     --c; 
    } 

end: 

    putchar(c); 
    putchar('\n'); 

    return 0; 
} 

Zusammengestellt mit gcc -S, keine Optimierungen, hier ist die Ausgabe:

.file "goto_skip_41709548.c" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    subq $16, %rsp 
    call getchar 
    movl %eax, -4(%rbp) 
    cmpl $121, -4(%rbp) 
    jne .L2 
    addl $1, -4(%rbp) 
    jmp .L3 
.L2: 
    subl $1, -4(%rbp) 
.L3: 
    movl -4(%rbp), %eax 
    movl %eax, %edi 
    call putchar 
    movl $10, %edi 
    call putchar 
    movl $0, %eax 
    leave 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4" 
    .section .note.GNU-stack,"",@progbits 

Der Compiler hat genau die gleiche Ausgabe für den gleichen Code mit die goto entfernt. Verifizierte mit einem diff:

λ> diff w_goto.s wo_goto.s 
1c1 
< .file "goto_skip_41709548.c" 
--- 
> .file "no_goto_skip_41709548.c" 
+0

Oh danke für die heads up :) –

5

Wenn Ihr Code kompiliert, wäre es wahrscheinlich (dh auf den meisten anständigen Compiler) ähnlich den folgenden Pseudo-Code, um etwas zu übersetzen:

if (a != true) 
     jump else 

    foo() * will not execute if a is false 
      * because of the `jump else` 
    jump end 

else: 
    bar() * will not execute if a is true 
      * because of the `jump end` 

end: 

wo else und end sind Etiketten (versuchen sie es mit echten und falschen a auf Papier zu laufen).

Grundsätzlich werden beide Schnipsel auf die gleiche kompilierte Version übersetzen, und Ihre goto wird keine Wirkung auf das Ergebnis haben, weil es in der Verzweigung enthalten ist. In den meisten Fällen wird Ihr Compiler für weitere 2 Millisekunden zum Schwitzen gebracht, um ihn zu erkennen und zu ignorieren.

Wenn man die Leistung betrachtet, hat ein manueller Sprung, der halb impliziert ist, nicht viel Bedeutung. Breaking-Loops, Nicht-Re-Deklaration und andere Programmierer-Ende-Optimierungsaktivitäten tragen viel mehr dazu bei.


Als Anmerkung, ist diese Verzweigung wie Montagebedingungen gebaut werden, wie man speichert die logische Operation in einem Register und vergleichen Sie es zu prüfen, ob springen oder nicht. Ein genauerer Pseudo-Code würde

cmp a, true /or/ xor a, a ; 0 if true, 1 if false 
    jne else /or/ jnz else ; jump if not equal/zero 
    foo() 
    jmp end ; jump to 
else: 
    bar() 
end: 
Verwandte Themen