Gdy instrukcja continue jest używana w pętli kodu C, GCC tworzy nową etykietę z instrukcją nop tuż przed końcem bloku pętli i przeskakuje do niego, zamiast skakać do końca samego bloku pętli. Na przykład, następujące kod CGCC wygenerował zespół równoważny instrukcji continue w C
for (i=0; i<10; i++) {
puts("blah\n");
if (i < 10) continue;
puts("This shouldn't be printed.\n");
}
wytwarza następujący równoważnik ASM (gcc -S)
movl $0, 28(%esp)
jmp L2
L5:
movl $LC0, (%esp)
call _puts
cmpl $9, 28(%esp)
jle L7
L3:
movl $LC1, (%esp)
call _puts
jmp L4
L7:
nop
L4:
incl 28(%esp)
L2:
cmpl $9, 28(%esp)
jle L5
(if (I < 10) część jest włożony tak, że kompilator robi” t "zoptymalizuj" sekcję, usuwając wszystko, co następuje po instrukcji continue).
Moje pytanie brzmi: dlaczego nie przejść bezpośrednio do L4? IMO mogliśmy równie dobrze przejść do L4, czy coś mi brakuje?
Dzięki za szybką odpowiedź! -O1 zmyliło, chociaż przepływ programu po optymalizacji wydaje się teraz nieco mniej intuicyjny - chyba że się mylę, pętla wydaje się teraz częściowo rozwinięta. Ciekawi mnie teraz, czy istnieje zachęta do stworzenia etykiety za pomocą instrukcji nop. Czy jest jakaś sytuacja, w której to podejście zapobiegałoby temu, co by się stało, gdyby ktoś skoczył bezpośrednio na L4? – susmits
Do celów debugowania można ustawić punkt przerwania w etykiecie L7 - trudno byłoby złamać dalej sprawę kontynuacji, jeśli jej tam nie było. – nos
@susmits: Z -O1 zestaw jest mniej szczegółowy, ale pętla nie jest rozwijana (z -O3 możesz zobaczyć rozwiniętą wersję - zauważ, że nie zawiera nawet testu i <10 lub 2. puts()) . Generalnie tworzenie etykiety i niewykonywanie takich optymalizacji bardzo pomaga w debugowaniu. –