Czy „for (;;)” jest szybsze niż „while (TRUE)”? Jeśli nie, dlaczego ludzie go używają?

164
for (;;) {
    //Something to be done repeatedly
}

Często widziałem takie rzeczy, ale myślę, że jest to raczej dziwne… Czy nie byłoby o wiele jaśniej powiedzieć while(true), czy coś w tym stylu?

Zgaduję, że (co jest powodem, dla którego wielu programistów ucieka się do tajemniczego kodu) jest to niewielki margines szybciej?

Dlaczego i czy naprawdę warto? Jeśli tak, dlaczego nie zdefiniować tego w ten sposób:

#define while(true) for(;;)

Zobacz także: Co jest szybsze: while (1) czy while (2)?

Chris Cooper
źródło
51
Co to jest TRUE???
AnT
20
@Steven Sudit: Co TRUEma wspólnego z C? Standardowe makro dla prawdziwego wyniku boolen w C99 jest nadal true. Skąd się wziął TRUE?
AnT
31
To makro nie działa, #define EVER ;;zostało jednak użyte w IOCCC .. :)
18
Czy nie jest to makro do #define while(TRUE)deklarowania makra, które przyjmuje jeden argument, TRUEktóry nigdy nie jest używany, a zatem zamienia każdą pojedynczą pętlę while w programie w nieskończoną pętlę?
AshleysBrain
9
@Steven Sudit: Nie. Nie ma „standardowego makra w VS 6.0”. Makro TRUEpochodzi z plików nagłówkowych powiązanych z Windows API. Nie jest w żaden sposób powiązany z VS 6.0. I, jak powiedziałem wcześniej, nie ma to nic wspólnego ani z C, ani z C ++. W C ++ „prawdziwy” literał to po prostu true(również w VS 6.0), w C89 / 90 w ogóle czegoś takiego nie ma, aw C99 jest to makro true. Dotyczy to wszystkich kompilatorów C / C ++.
AnT

Odpowiedzi:

262
  1. To nie jest szybsze.
  2. Jeśli naprawdę ci zależy, skompiluj z wyjściem asemblera dla swojej platformy i zobacz.
  3. To nie ma znaczenia. To nigdy się nie liczy. Napisz swoje nieskończone pętle, jak chcesz.
Ben Zotto
źródło
227
Intuicyjnie optymalizacja nieskończonej pętli daje możliwość nieskończonego przyspieszenia. Dobrze, że nie programujemy na intuicji. :-)
Steven Sudit
5
Przypuszczam, że masz rację. Myślę, że dałem się wciągnąć w „religijne” debaty o drobiazgach. Dziękuję za otrząśnięcie mojego sumienia. : D
Chris Cooper
6
@Steven LOL, to interesujące, ale weź pod uwagę, że jedynym scenariuszem, w którym faktycznie osiągnąłeś ten potencjał nieskończonego przyspieszenia, jest sytuacja, w której pętla nigdy się nie zrywa i naprawdę działa w nieskończoność, co prawdopodobnie jest błędem lub, jeśli było zamierzone, będzie nieskończone oczekiwanie, zanim osiągnie ten potencjał.
AaronLS
7
@Chris. W programowaniu, tak jak w życiu, debaty religijne są warte twojego czasu tylko dla rzeczy naprawdę ważnych. To po prostu nie jest jedna z tych rzeczy. Jak widać, każdy ma ulubiony sposób pisania niekończącej się pętli. Wybierz dla siebie to, co sprawia, że ​​jesteś najszczęśliwszy z małych rzeczy, a następnie uruchom profiler na kodzie, który ma znaczenie. :)
Ben Zotto
3
To miało znaczenie, ponieważ niektóre wczesne kompilatory na niektórych platformach ładowały stałą i wykonywały warunkowy skok. Który w tamtych czasach miał znaczenie.
peterchen
176

wolę for(;;) z dwóch powodów.

Po pierwsze, niektóre kompilatory wyświetlają ostrzeżenia dotyczące while(true) (coś w rodzaju „warunek pętli jest stały”). Unikanie ostrzeżeń jest zawsze dobrą rzeczą.

Po drugie, myślę, że for(;;)jest jaśniejszy i bardziej wymowny. Chcę nieskończonej pętli. To dosłownie ma ma warunku, nie zależy od niczego. Chcę tylko, żeby trwało to wiecznie, dopóki nie zrobię czegoś, aby się z tego wyrwać.

Podczas gdy z while(true) cóż, co ma wspólnego z czymkolwiek? Nie interesuje mnie pętla, dopóki prawda nie stanie się fałszem, co dosłownie mówi ta forma (pętla, gdy prawda jest prawdziwa). Chcę tylko zapętlić.

I nie, nie ma absolutnie żadnej różnicy w wydajności.

jalf
źródło
73
+1 za unikanie ostrzeżeń. Ale jeśli chodzi o jasność, uważam, że jest jaśniejsza niż w tym kontekście. Myślę, że ten aspekt sprowadza się do osobistych preferencji.
Tim
14
Tak, upodobanie i nawyk. Jeśli nie jesteś przyzwyczajony do widzenia for(;;), będzie to oczywiście dziwnie wyglądać. Ale radziłbym spróbować się do tego przyzwyczaić, ponieważ jest to powszechny idiom i znowu się z nim spotkasz. ;)
jalf Kwietnia
7
komentarz jalfa o tym, że jest idiomatyczny, jest tutaj naprawdę odpowiedzią. Jest powszechnie używany do określenia „nieskończonej pętli” po prostu dlatego, że jest to powszechnie używany sposób zapisu „nieskończonej pętli” w C. Nie musi być dobrego powodu dla idiomu - to tylko samonapędzająca się konwencja.
kawiarnia
7
@Steve: Nie rozumiem, dlaczego kiedykolwiek bym używał for(;condition;). To właśnie pętli while jest za . Ale tak jak powiedziałem, w przypadku nieskończonej pętli nie chcę, aby kompilator porównywał jakiekolwiek warunki. Naiwnie, z whilepętlą, musiałby przetestować truekażdą iterację (oczywiście nawet najgłupszy kompilator tego nie zrobiłby, ale przeszkadza mi ta zasada. Wydaje mi się, że zbytnio określam kod), podczas gdy z a for(;;)you dosłownie mówisz „nie ma warunku do sprawdzenia. Po prostu zapętlaj”. Uważam, że jest to najbliższy odpowiednik twojego wyimaginowanegoloop {...}
jalf
32
Twój kompilator jest do niczego, jeśli while(true)wyświetla ostrzeżenie.
Albert,
56

Osobiście używam, for (;;)ponieważ nie ma w nim żadnych liczb, to tylko słowo kluczowe. Wolę go while (true), while (1), while (42), while (!0)etc etc.

ta.speot.is
źródło
38
0, 1 i nieskończoność to dopuszczalne liczby magiczne, rozszerzenie 0 i 1 na fałsz i prawda nie jest stratą. truenie jest bardziej magiczną liczbą niż formagiczne słowo kluczowe lub które for(;;)używa implikowanej magicznej nieskończoności. ( while (42)jest rzeczywiście obrzydliwością.)
38
Tangent: jeden z moich profesorów CS powiedział, że „w programowaniu są tylko trzy liczby: 0, 1 i n. Cokolwiek innego nazywa się liczbą magiczną”.
Ben Zotto,
21
while (42) jest najfajniejszy, nie daje innego wyniku w odniesieniu do while (1), while (true) lub while (! 0) i ma znaczenie filozoficzne . Przypuszczam, że i tak for(;;)jest analizowany szybciej niż inne
ShinTakezou,
2
@ShinTakezou znacznie lepiej #define LIFE 42 while (LIFE):)
mr5
1
dobrze while(true)nie zawiera też żadnej liczby. a dla (;;) nie jest słowem kluczowym
RiaD
49

Z powodu Dennisa Ritchiego

  • Zacząłem używać, for (;;)ponieważ tak robi to Dennis Ritchie w K&R, a ucząc się nowego języka, zawsze staram się naśladować sprytnych facetów.

  • To jest idiomatyczne C / C ++. Prawdopodobnie lepiej na dłuższą metę przyzwyczaić się do tego, jeśli planujesz dużo robić w przestrzeni C / C ++.

  • Twój #definenie zadziała, ponieważ rzecz # define'd musi wyglądać jak identyfikator C.

  • Wszystkie nowoczesne kompilatory będą generować ten sam kod dla obu konstrukcji.

Mark Harrison
źródło
10
Tak, dzięki temu wiesz, że ktoś nauczył się C od K&R, tak jak powinno się tego nauczyć. Za każdym razem, gdy widzę while(TRUE), podejrzewam, że programista jest nowicjuszem w C lub nauczył się C z książki For Dummies.
Kristopher Johnson
13
Słyszałem, że ci nowicjusze również używają nowomodnego stylu definicji funkcji .
Justin
46

Z pewnością nie jest szybszy w żadnym rozsądnym kompilatorze. Obaj zostaną zestawieni w bezwarunkowe skoki. Wersja for jest łatwiejsza do wpisania (jak powiedział Neil) i będzie zrozumiała, jeśli zrozumiesz składnię pętli.

Jeśli jesteście ciekawi, oto co daje mi gcc 4.4.1 dla x86. Oba używają instrukcji x86 JMP .

void while_infinite()
{
    while(1)
    {
    puts("while");
    }
}

void for_infinite()
{
    for(;;)
    {
    puts("for");
    }
}

kompiluje się do (częściowo):

.LC0:
.string "while"
.text
.globl while_infinite
    .type   while_infinite, @function
while_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L2:
    movl    $.LC0, (%esp)
    call    puts
    jmp .L2
    .size   while_infinite, .-while_infinite
    .section    .rodata
.LC1:
    .string "for"
    .text
.globl for_infinite
    .type   for_infinite, @function
for_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L5:
    movl    $.LC1, (%esp)
    call    puts
    jmp .L5
    .size   for_infinite, .-for_infinite
Matthew Flaschen
źródło
Wątpię, czy jest szybszy nawet w trybie debugowania.
Steven Sudit
106
for_infinitejest szybszy; 2 mniej znaków do puts.
Dave Jarvis,
43

Wolę, for (;;)ponieważ jest najbardziej spójny w różnych językach podobnych do C.

W C ++ while (true)jest w porządku, ale w C musisz zdefiniować nagłówek true, ale TRUEjest to również powszechnie używane makro. Jeśli używasz while (1)go poprawnie w C i C ++ oraz JavaScript, ale nie w Javie lub C #, które wymagają, aby warunek pętli był wartością logiczną, na przykład while (true)lub while (1 == 1). W PHP w słowach kluczowych nie jest rozróżniana wielkość liter, ale język preferuje wielkie litery TRUE.

Jednak for (;;)we wszystkich tych językach jest zawsze całkowicie poprawne.

Boann
źródło
9
Dziękuję za odpowiedź! Myślę, że jest to właściwie pierwsza odpowiedź, która pokazuje obiektywny sposób, który for (;;)jest lepszy.
Chris Cooper
8
Nie sądzę, żebym kiedykolwiek musiał pisać kod, który byłby poprawny w językach C, C ++, JavaScript, Java i C #. To różne języki.
Keith Thompson
6
@KeithThompson nie chodzi o pisanie kodu, który jest poprawny w wielu językach; Myślę, że chodzi o unikanie błędnych interpretacji między programistami z różnych środowisk.
Mauro Sampietro
6
@sam: Oba while (1)i for (;;)są powszechnymi idiomami dla nieskończonych pętli w C. Każdy, kto czyta program w C i ma problemy ze zrozumieniem któregokolwiek z nich, prawdopodobnie będzie miał problem z resztą kodu. Nie warto pisać kodu w C, który może być łatwo odczytany przez kogoś, kto nie zna C.
Keith Thompson
6
@KeithThompson Chociaż kompetentny czytelnik C powinien zdecydowanie znać oba idiomy, może to być również przydatne, jeśli pisarz jest programistą poliglotą. W mojej ostatniej pracy na co dzień pracowałem w JS, ActionScript i PHP i ujednolicenie sposobu pisania kodu (tam, gdzie ma to sens) może przyspieszyć programowanie i ułatwić konserwację.
Ionoclast Brigham
21

Osobiście wolę for (;;)idiom (który zostanie skompilowany do tego samego kodu co while (TRUE).

Używanie while (TRUE)może być bardziej czytelne w pewnym sensie, zdecydowałem się użyć for (;;)idiomu, ponieważ się wyróżnia .

Konstrukcja nieskończonej pętli powinna być łatwo zauważalna lub wywoływana w kodzie i osobiście uważam, że for (;;)styl robi to nieco lepiej niż while (TRUE)lub while (1).

Przypominam też, że niektóre kompilatory wyświetlają ostrzeżenia, gdy kontrolujące wyrażenie pętli while jest stałą. Nie wydaje mi się, żeby to się zdarzało zbyt często, ale wystarczy mi możliwość fałszywych ostrzeżeń, abym chciał tego uniknąć.

Michael Burr
źródło
17

Widziałem, że niektórzy wolą to, ponieważ mają #define gdzieś w ten sposób:

#define EVER ;;

Co pozwala im napisać to:

for (EVER)
{
    /* blah */
}
rmeador
źródło
24
Też to widziałem; ale nie jest to wystarczający powód, by go preferować. Jako opiekun nadal musiałbyś sprawdzić definicję makra, aby mieć pewność, że zrobiło to, czego się spodziewałeś, podczas gdy oryginalny kod był wystarczająco jasny. RTOS VxWorks ma FOREVERzdefiniowane makro for(;;), ale to nie jest lepsze. Makra IMO nie powinny być używane do „wymyślania” nowego języka.
Clifford,
8
Właściwie celem makr w niektórych językach jest wymyślenie nowej składni. Ale niezależnie od „for (EVER)” w C / C ++ jest ohydne.
Dan Olson,
15
Niektórzy ludzie robią śmieszne rzeczy, na przykład jeśli lubią Pascala, mówią #define BEGIN {i #define END }. Widziałem nawet, #define DONKEYS_FLY (0)żeby mogli powiedzieć if DONKEYS_FLY .... Kto powiedział, że oprogramowanie jest nudne?
Mike Dunlavey
11
W Kalifornii wierzę, że musisz #define for (;;) LIKE_FOREVER
Martin Beckett
1
Nie mogłem się oprzeć: #define never while(0)i#define always
alfC
16

A co z (jeśli twój język to obsługuje):

start:
/* BLAH */
goto start;
klecić
źródło
... co powinno generować identyczne dane wyjściowe w rękach każdego rozsądnego kompilatora.
Ben Zotto,
9
+1! Nie poprawia gototo wielu wad, ale jeśli algorytm, który próbujesz zaimplementować, pochodzi z schematu blokowego, jest to najbardziej bezpośrednie tłumaczenie.
Edmund,
4
Osobiście mam utylitarny pogląd na temat goto. Nie ma ptaków drapieżnych. Ptaki drapieżne to ludzie. I to ludzie zaczęli używać goto do tworzenia kodu spaghetti. Również zestawione wyjście pętli wygląda mniej więcej tak. Zestawy instrukcji dla komputerów nie zawierają pojęć „for” ani „while”, po prostu „jump”.
josaphatv
nigdy przenigdy nie używaćgoto
Edward Karak
Naprawdę fajną rzeczą gotojest to, że nie musisz się martwić, że ktoś doda a, breakaby Twoja pętla była mniej nieskończona. (chyba że jesteś już w innej pętli whilelub foroczywiście ...)
12

Nie ma różnicy pod względem generowanego kodu maszynowego.

Jednak, aby przezwyciężyć ten trend, argumentowałbym, że forma while (TRUE) jest znacznie bardziej czytelna i intuicyjna niż for (;;), a czytelność i przejrzystość są znacznie ważniejszymi powodami dla wytycznych kodowania niż jakiekolwiek powody, dla których ja ' słyszałem o podejściu for (;;) (wolę oprzeć moje wytyczne dotyczące kodowania na solidnym uzasadnieniu i / lub dowodzie skuteczności).

Jason Williams
źródło
6
To zależy od twojego języka. for(;;)jest tradycyjnym sposobem na zrobienie tego w C i C ++. while(true)wydaje się być konwencją w C # i Javie i innych językach. Twój przebieg może się różnić.
Billy ONeal
9
Tak, a ktoś, kto nie jest zbyt zaznajomiony z C lub C ++, może uznać STRING_SCAN_FORMATTED za bardziej czytelny niż sscanf, ale nie widać nikogo, kto umieszczałby #define STRING_SCAN_FORMATTED sscanf na początku swojego kodu.
ta.speot.is
4
Powiedziałbym, że idiomatyczny sposób na zrobienie tego powinien być jak najbardziej czytelny dla twojego programisty. W przeciwnym razie naprawdę potrzebujesz lepszych programistów.
jalf Kwietnia
5
@despart: Jeśli ktoś nie jest wystarczająco zaznajomiony z C ++, aby rozpoznać ten idiom, to musi trzymać się z daleka od mojej bazy kodu.
Billy ONeal
4
Zgadzam się, że sposób idiomatyczny powinien być jak najbardziej czytelny. Dlatego idiomatyczne sposoby zawsze muszą być kwestionowane i zmieniane w miarę ewolucji języków i praktyk. Minęły lata, zanim okropny „idiomatyczny” styl kodowania K&R został zastąpiony nowoczesnym, bardziej czytelnym stylem, ale tak się stało.
Jason Williams,
11

Nie tylko dobrze znany wzorzec, ale standardowy idiom w C (i C ++)

James McLeod
źródło
3
Tak, i myślę, że niektórzy kompilatorzy ostrzegają z while (true)tego samego powodu co dalej if (true).
Steven Sudit
11
while(true)

generuje ostrzeżenie w programie Visual Studio (stan jest stały). Większość miejsc, w których pracowałem, kompiluje kompilacje produkcyjne z ostrzeżeniami jako błędami. Więc

for(;;)

jest preferowany.

Michael
źródło
7
jakiej wersji Visual Studio używasz? W 2008 roku nie dostaję tego ostrzeżenia, nawet na poziomie ostrzeżenia 4.
Jörgen Sigvardsson,
11

Oba powinny być takie same, jeśli kod jest zoptymalizowany przez kompilator. Aby wyjaśnić, co rozumiem przez optymalizację, oto przykładowy kod napisany w MSVC 10:

int x = 0;

while(true) // for(;;)
{
    x +=1;

    printf("%d", x);
}

Jeśli zbudujesz go w trybie debugowania ( bez żadnej optymalizacji (/ Od) ), demontaż pokazuje wyraźną różnicę. Istnieją dodatkowe instrukcje dotyczące truestanu wewnątrz while.

while(true)
00D313A5  mov         eax,1                //extra 
00D313AA  test        eax,eax              //extra
00D313AC  je          main+39h (0D313B9h)  //extra
    {
        x +=1;
00D313AE  mov         eax,dword ptr [x]  
00D313B1  add         eax,1  
00D313B4  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D313B7  jmp         main+25h (0D313A5h)  


for(;;)
    {
        x +=1;
00D213A5  mov         eax,dword ptr [x]  
00D213A8  add         eax,1  
00D213AB  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D213AE  jmp         main+25h (0D213A5h)  

Jeśli jednak zbudujesz swój kod w trybie wydania (z domyślną maksymalną prędkością (/ O2) ), otrzymasz te same dane wyjściowe dla obu. Obie pętle są zredukowane do jednej instrukcji skoku.

for(;;)
    {
        x +=1;
01291010  inc         esi  

        printf("%d", x);
    ...
    }
0129101C  jmp         main+10h (1291010h)  

    while(true)
    {
        x +=1;
00311010  inc         esi  

        printf("%d", x);
    ...
    }
0031101C  jmp         main+10h (311010h)  

Niezależnie od tego, którego użyjesz, nie ma znaczenia, ponieważ przyzwoity kompilator z optymalizacją prędkości jest włączony.

SylvanBlack
źródło
To naprawdę bardzo dobra uwaga! Bez optymalizacji nawet nowoczesne kompilatory będą różnić się kilkoma instrukcjami.
9

To kwestia osobistych preferencji, który sposób jest szybszy. Osobiście jestem typem dotykowym i nigdy nie patrzę na klawiaturę, podczas programowania - potrafię wpisywać dotykowo wszystkie 104 klawisze na swojej klawiaturze.

Uważam, że szybciej wpisuję „while (TRUE)”.

Dodałem w myślach kilka pomiarów ruchu palca i zsumowałem je. „for (;;)” ma około 12 szerokości klawiszy ruchów do tyłu i do czwartego (między klawiszami home a klawiszami oraz między klawiszami home a klawiszem SHIFT), natomiast (TRUE) ma około 14 szerokości klawiszy ruchów wstecz i czwarty.

Jednak podczas pisania tego drugiego jestem znacznie mniej podatny na błędy. Myślę mentalnie słowami naraz, więc szybciej wpisuję rzeczy takie jak „nIndex” niż akronimy takie jak „nIdx”, ponieważ muszę w myślach przeliterować litery, zamiast wypowiadać je w myślach i pozwalać palcom na automatyczne pisanie -wpisz słowo (jak jazda na rowerze)

(Mój test porównawczy TypingTest.com = 136 WPM)

Mark Rejhon
źródło
3
Myślę, że OP odnosił się do szybkości działania, a nie szybkości pisania.
Wiem. Musiałem tylko zakryć tę bazę.
Mark Rejhon,
7
s / osobiste preferencje / indywidualny nawyk /
SamB
@SamB: Głos za pozytywnym komentarzem dla s ///. xD I tak, chociaż sugerowałem, że może to być spowodowane szybkością działania, nie znałem właściwej odpowiedzi. Gdyby to było to, byłbym szczęśliwy.
Chris Cooper,
Uruchom time head -10 >/dev/null, wpisz co 10 razy i zmierz wyniki. Założę się, że będziesz szybszy, for(;;)chyba że oszukasz. Byłem o około 14%.
PSkocik
6

Wszystkie dobre odpowiedzi - zachowanie powinno być dokładnie takie samo.

JEDNAK - tylko przypuśćmy, że ZROBIŁO różnicę. Załóżmy, że jeden z nich otrzymał 3 dodatkowe instrukcje na iterację.

Czy powinno cię to obchodzić?

TYLKO jeśli to, co robisz wewnątrz pętli, jest prawie niczym , co prawie nigdy nie ma miejsca.

Chodzi mi o to, że jest mikro-optymalizacja i makro-optymalizacja. Mikro-optymalizacja jest jak „strzyżenie, aby schudnąć”.

Mike Dunlavey
źródło
3
Jak często widzisz ludzi mówiło się preferować ++inad i++?
Dennis Zickefoose
7
@Dennis Zickefoose: Różnica między ++ii i++może być potencjalnie znacząca, jeśli ijest to instancja klasy, a nie wbudowana, a kompilator nie stosuje trywialnej optymalizacji. Rada jest taka, aby nabrać nawyku, aby nie złapał Cię, gdy się liczy.
Clifford,
5
W ++iVS i++jest to, że nic Cię nie kosztuje, aby dokonać „optymalizacji”. To prawda, w większości przypadków nie robi to żadnej różnicy, ale są równie łatwe do wpisania, więc dlaczego nie preferować potencjalnie najbardziej wydajnych domyślnie? Przypuszczam, że to samo dotyczy tutaj. Jeśli jeden był odrobinę szybszy od drugiego, dlaczego nie wybrać szybszego? Co stracilibyśmy, robiąc to? Oba są dość łatwe do odczytania i przepisania.
jalf
2
@Dennis Zickefoose: Masz rację. Widzę to często na SO, a komentarz Clifforda jest słuszny. Ponadto jest coś, czego nie widzę zbyt wiele w SO, a to jest sposób na optymalizację makro, na przykład przyspieszenie 43x: stackoverflow.com/questions/926266/… . Dlatego zastanawiam się nad naszymi priorytetami.
Mike Dunlavey
2
@Mike: Tak, ale to porównanie jabłek z pomarańczami. Strzyżenie zajmuje rzeczywisty czas, a prawdopodobnie nawet pieniądze. Zgadzam się, że to taka mikrooptymalizacja, że ​​tak naprawdę nie ma to znaczenia. Ale to też nic nas nie kosztuje . jeśli mogę wybrać jazdę w lewo lub w prawo, a odległość jest taka sama, teren jest taki sam, wszystko jest takie samo, z wyjątkiem tego, że lewa ścieżka ma pewne marginalne mikroskopijne korzyści, dlaczego nie skręcić w lewo? Masz rację, to nie jest imponujący argument. Ale kiedy koszt jest dosłownie zerowy, nie widzę powodu, by preferować mniej optymalną trasę.
jalf
5

Nie wyobrażam sobie, żeby wartościowy kompilator wygenerował inny kod. Nawet gdyby tak było, nie byłoby możliwości określenia, bez przetestowania konkretnego kompilatora, który jest bardziej wydajny.

Jednak sugeruję, abyś wolał for(;;)z następujących powodów:

  • kilka kompilatorów, których użyłem, wygeneruje stałe ostrzeżenie o wyrażeniu while (true) z odpowiednimi ustawieniami poziomu ostrzeżenia.

  • w twoim przykładzie makro TRUE może nie być zdefiniowane zgodnie z oczekiwaniami

  • istnieje wiele możliwych wariantów w nieskończonej pętli while takie jak while(1), while(true), while(1==1)itp .; więc for(;;)prawdopodobnie spowoduje większą spójność.

Clifford
źródło
PRAWDA może nie być #define PRAWDA 1, ale każda baza kodu, w której while(TRUE)wartościowane jako while(0)prawdopodobnie nie odniesie korzyści for(;;).
Justin
@Justin: Zgadzam się, byłoby to naprawdę przewrotne i nie jest to najsilniejszy z trzech argumentów, ale Bjarne Stoustrup używa podobnego argumentu, aby uniknąć makra NULL w C ++. while(true)powinno być preferowane w każdym przypadku. W C ++ booljest zarezerwowane, aw C zdefiniowane w C stdbool.h (czyniąc go mniej bezpiecznym w C). for(;;)usuwa wszelkie wątpliwości.
Clifford,
5
for(;;Sleep(50))
{
    // Lots of code
}

Jest jaśniejsze niż:

while(true)
{
    // Lots of code
    Sleep(50);
}

Nie dotyczy to sytuacji, gdy nie używasz Sleep().

Armada
źródło
1
To cholernie zły kod, zamiast uśpienia należy użyć timera, więc jest to zły przykład
ST3
12
@ ST3 - Tak, masz rację. Mój kod jest okropny. Powinienem bardziej się postarać następnym razem, gdy wykonam nieskończoną pętlę.
Armada
1
@Frammo - zależy od twojego systemu operacyjnego, ale zwykle coś w stylutimerService.scheduleRepeating (50, [] () { /* lots of code */ });
Periata Breatta
2
Nie ma nic czystego w wywoływaniu funkcji takiej jak sleep wewnątrz pętli for w ten sposób
Greg,
1
OMG, timerService.scheduleRepeating (50, [] () {}) jest po prostu o wiele łatwiejsze do wpisania i zrozumienia niż sleep (50).
Cool Javelin
4

Pętla „na zawsze” jest popularna w systemach wbudowanych jako pętla w tle. Niektórzy implementują to jako:

for (; ;)
{
 // Stuff done in background loop
}

Czasami jest to realizowane jako:

while (TRUE /* or use 1 */)
{
 // Stuff done in background loop
}

A jeszcze inna implementacja to:

do
{
 // Stuff done in background loop
} while (1 /* or TRUE */);

Kompilator optymalizujący powinien generować taki sam lub podobny kod asemblera dla tych fragmentów. Jedna ważna uwaga: czas wykonywania pętli nie jest dużym problemem, ponieważ te pętle trwają w nieskończoność, a sekcja przetwarzania zajmuje więcej czasu.

Thomas Matthews
źródło
8
Jeśli kompilator generuje dla nich inny kod, czas porzucić kompilator i pobrać jeden z ostatnich dwóch dekad.
GManNickG
5
„czas wykonania pętli nie jest wielkim problemem, ponieważ te pętle
trwają
3
@Blindy - ponieważ jest to błąd, niepokojące jest ułamek czasu wykonania spędzonego na przetwarzaniu logiki pętli lub ilość logiki pętli na jednostkę użytecznej pracy, z których żadna nie jest wspomagana przez nieskończoną pętlę
Ben Voigt
3

Zakładam, że (true) jest bardziej czytelne niż for (;;) - wygląda na to, że programista przeoczył coś w pętli for :)

nik
źródło
Zależy mi na szybkości. Zwłaszcza jeśli istnieje optymalizacja, która wpłynie na mój kod w nieskończoność.
Kowalski
2

Najważniejszym powodem używania „for (;;)” jest obawa przed używaniem „while (TRUE)” podczas programowania eksploracyjnego. Łatwiej jest kontrolować liczbę powtórzeń za pomocą „for”, a także łatwiej jest przekształcić pętlę „for” w nieskończoną.

Na przykład, jeśli konstruujesz funkcję rekurencyjną, możesz ograniczyć liczbę wywołań tej funkcji przed konwersją na nieskończoną pętlę.

    for(int i=0;i<1000;i++) recursiveFunction(oneParam);

Kiedy jestem pewien swojej funkcji, konwertuję ją na nieskończoną pętlę:

    for(;;) recursiveFunction(oneParam);
Ignacio Cortorreal
źródło
3
Pierwsza pętla zawiera błąd składni (brak średnika).
Jens
3
Ha! Tym samym demonstrując wady for (;;);)
Andrew