Działanie pętli for krok po kroku

0

Dzień dobry.
Chciałbym się dowiedzieć jak dokładnie krok po kroku działa pętla for.
Moja propozycja wyjaśnienia jest następująca.

for ( pole_inicjalizacji; pole_warunku; pole_dodatkowych_instrukcji)
{
instrukcje_do_wykonania_gdy_warunek_jest_spełniony;
}

Gdy pętla zostaje wywołana, to najpierw wykonywane są polecenia z części pole_inicjalizacji.
Potem sprawdzany jest warunek (pole_warunku) i jeśli jest spełniony to wykonywane są polecenia
z części instrukcje_do_wykonania_gdy_warunek_jest_spełniony; (czyli wykonywane jest
ciało pętli for. W kolejnym kroku wykonywane są polecenia z części pole_dodatkowych_instrukcji.

I potym pętla znowu przechodzi do pole_warunku i jeśli ten jest spełniony to wykonuje są polecenia
z części instrukcje_do_wykonania_gdy_warunek_jest_spełniony;, następnie przechodzi do
części pole_dodatkowych_instrukcji.
I teraz ponownie do zabiera się do sprawdzania warunku (przechodzi do części pole_warunku), itd.

Czy dobrze zrozumiałem działanie pętli for?
Najpierw pole_warunku [krok 1], potem instrukcje_do_wykonania_gdy_warunek_jest_spełniony (ciało pętli) [krok 2],
następnie pole_dodatkowych_instrukcji [krok 3]. I znowu od początku pętla wraca do pole_warunku [krok 1], itd.
I przy pierwszym uruchomieniu pętli for wykonywane są polecenia z częsci pole_inicjalizacji (te polecenia są wykonywane
tylko przy pierwszym uruchomieniu pętli, po ich wykonaniu pętla przechodzi do kroku 1, a więc do części pole_warunku.

Czy tak?

0
for(int i = 0; i < 10; ++i) 
    cout << i << endl;

można przetłumaczyć na

int i = 0;
while(i < 10){
    cout << i << endl;
    ++i;
}
4

Sprawdźmy!

int main(){
	for(int i=0;i<10;i++){
		
	}
	return 0;
}

g++ -S daje nam

	.file	"test.cpp"
	.def	___main;	.scl	2;	.type	32;	.endef
	.text
.globl _main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
LFB0:
	pushl	%ebp
LCFI0:
	movl	%esp, %ebp
LCFI1:
	andl	$-16, %esp
LCFI2:
	subl	$16, %esp
LCFI3:
	call	___main
	movl	$0, 12(%esp)
	jmp	L2
L3:
	addl	$1, 12(%esp)
L2:
	cmpl	$9, 12(%esp)
	setle	%al
	testb	%al, %al
	jne	L3
	movl	$0, %eax
	leave
LCFI4:
	ret
LFE0:

z czego oczywiście interesuje nas generalnie:

	movl	$0, 12(%esp)
	jmp	L2
L3:
	addl	$1, 12(%esp)
L2:
	cmpl	$9, 12(%esp)
	setle	%al
	testb	%al, %al
	jne	L3
	movl	$0, %eax
	leave

I co tutaj widzimy? Najpierw mamy:

	movl	$0, 12(%esp)

czyli ustawienie wartości początek zmiennej i (czyli 12(%esp), bo jak widać jest 12 bajtów od stack pointera) na 0.
Następnie mamy skok do L2 a tam

	cmpl	$9, 12(%esp)
	setle	%al
	testb	%al, %al
	jne	L3

Czyli porównanie naszej zmiennej z liczbą 9 a potem skok do L3 jeśli nasza zmienna nie jest równa 9.
W L3 mamy

	addl	$1, 12(%esp)

czyli inkrementacje naszej zmiennej.

Podsumowując mamy:

  1. Wykonanie operacji początkowych dla pętli.
  2. Sprawdzenie warunku końca pętli, jeśli fałszywy to skok do 3
  3. Wykonanie operacji kroku pętli, skok do 2.
  4. Koniec pętli.
0
for ( pole_inicjalizacji; pole_warunku; pole_dodatkowych_instrukcji)
{
instrukcje_do_wykonania_gdy_warunek_jest_spełniony;
}

oznacza

{
    pole_inicjalizacji;
    while (pole_warunku)
    {
        instrukcje_do_wykonania_gdy_warunek_jest_spełniony;
        pole_dodatkowych_instrukcji;
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1