To było pytanie do wywiadu zadane przez kierownika wyższego szczebla.
Który jest szybszy?
while(1) {
// Some code
}
lub
while(2) {
//Some code
}
Powiedziałem, że oba mają tę samą szybkość wykonywania, ponieważ wyrażenie wewnątrz while
powinno ostatecznie ocenić na true
lub false
. W takim przypadku zarówno ocena, jak true
i brak dodatkowych instrukcji warunkowych wewnątrz while
warunku. Oba będą miały tę samą szybkość wykonywania i wolę while (1).
Ale ankieter powiedział pewnie: „Sprawdź swoje podstawy. while(1)
Jest szybszy niż while(2)
”. (Nie testował mojej pewności siebie)
Czy to prawda?
Zobacz także: Czy „for (;;)” jest szybsze niż „while (TRUE)”? Jeśli nie, dlaczego ludzie z niego korzystają?
c
performance
while-loop
Nikole
źródło
źródło
0x100000f90: jmp 0x100000f90
(adres oczywiście się zmienia) dla obu fragmentów. Ankieter prawdopodobnie zabezpieczył się przed testem rejestrowym w porównaniu z prostym skoczkiem z oznaczeniem. Zarówno pytanie, jak i ich przypuszczenie są kulawe.Odpowiedzi:
Obie pętle są nieskończone, ale możemy zobaczyć, która z nich pobiera więcej instrukcji / zasobów na iterację.
Korzystając z gcc, skompilowałem dwa następujące programy do montażu na różnych poziomach optymalizacji:
Nawet bez optymalizacji (
-O0
) wygenerowany zestaw był identyczny dla obu programów . Dlatego nie ma różnicy prędkości między dwiema pętlami.Dla odniesienia tutaj jest wygenerowany zespół (przy użyciu
gcc main.c -S -masm=intel
flagi optymalizacji):Z
-O0
:Z
-O1
:Z
-O2
i-O3
(ta sama moc wyjściowa):W rzeczywistości zespół wygenerowany dla pętli jest identyczny dla każdego poziomu optymalizacji:
Najważniejsze bity to:
Nie potrafię dobrze czytać asemblera, ale jest to oczywiście bezwarunkowa pętla.
jmp
Instrukcja bezwarunkowo resetuje programu tyłu do.L2
etykiety bez nawet porównując wartość przed prawdą, i oczywiście od razu robi to ponownie, aż program jest jakoś skończyło. Odpowiada to bezpośrednio kodowi C / C ++:Edytować:
Co ciekawe, nawet bez optymalizacji wszystkie poniższe pętle dały dokładnie taki sam wynik (bezwarunkowy
jmp
) w zestawie:I nawet ku mojemu zdumieniu:
Sprawy stają się trochę bardziej interesujące dzięki funkcjom zdefiniowanym przez użytkownika:
Na
-O0
te dwa przykłady rzeczywiście wywołaćx
i wykonać porównania dla każdej iteracji.Pierwszy przykład (zwracanie 1):
Drugi przykład (powrót
sqrt(7)
):Jednak w
-O1
obu przypadkach oba wytwarzają ten sam zestaw co poprzednie przykłady (bezwarunkowyjmp
powrót do poprzedniej etykiety).TL; DR
W GCC różne pętle są kompilowane do identycznego zestawu. Kompilator ocenia stałe wartości i nie przeszkadza w faktycznym porównaniu.
Morał tej historii jest następujący:
źródło
-O
poziomie.jmp
wrócą do początku, albo całkowicie usuną pętlę.break
instrukcji), ale i tak ją przetestowałem i nie, nawet z kodem wewnątrz pętli skok jest absolutne i bezwarunkowe dla obuwhile(1)
iwhile(2)
. Jeśli naprawdę jesteś zaniepokojony, możesz sam przetestować innych.Tak,
while(1)
jest o wiele szybszy niżwhile(2)
, aby człowiek czytał! Jeśli widzęwhile(1)
w nieznanej bazie kodu, od razu wiem, co zamierzał autor, a moje oczy mogą przejść do następnej linii.Jeśli zobaczę
while(2)
, pewnie zatrzymam się i spróbuję dowiedzieć się, dlaczego autor nie napisałwhile(1)
. Czy palec autora poślizgnął się na klawiaturze? Czy opiekunowie tej bazy kodu używająwhile(n)
niejasnego mechanizmu komentowania, aby pętle wyglądały inaczej? Czy to prymitywne obejście fałszywego ostrzeżenia w uszkodzonym narzędziu do analizy statycznej? Czy jest to wskazówka, że czytam wygenerowany kod? Czy jest to błąd wynikający z niewłaściwego znalezienia i zastąpienia wszystkich, złego scalenia lub kosmicznego promienia? Może ta linia kodu ma robić coś zupełnie innego. Może miał to przeczytaćwhile(w)
lubwhile(x2)
. Lepiej znajdę autora w historii pliku i wyślę mu wiadomość e-mail „WTF” ... a teraz przełamałem swój kontekst mentalny.while(2)
while(1)
zajęłoby ułamek sekundy!Przesadzam, ale tylko trochę. Czytelność kodu jest naprawdę ważna. I warto o tym wspomnieć w wywiadzie!
źródło
svn-annotate
lubgit blame
(lub cokolwiek) i ogólnie ładowanie historii winy pliku zajmuje kilka minut. Potem w końcu zdecydowałem: „Ach, rozumiem, autor napisał ten wiersz, gdy wyszedł z liceum”, właśnie straciłem 10 minut ...1
.while(2)
w kodzie (aż do rozważenia: „Czy opiekunowie tej bazy kodu używają, podczas gdy (n) jako niejasny mechanizm komentowania, aby pętle wyglądały inaczej?” ). Więc nie, nie przesadzasz!Istniejące odpowiedzi pokazujące kod wygenerowany przez określony kompilator dla określonego celu z określonym zestawem opcji nie odpowiadają w pełni na pytanie - chyba że pytanie zostało zadane w tym konkretnym kontekście („Które jest szybsze przy użyciu gcc 4.7.2 dla x86_64 z domyślnymi opcjami? ”, na przykład).
Jeśli chodzi o definicję języka, w abstrakcyjnej maszynie
while (1)
ocenia stałą całkowitą1
iwhile (2)
ocenia stałą całkowitą2
; w obu przypadkach wynik jest porównywany dla równości do zera. Standard językowy absolutnie nic nie mówi o względnej wydajności obu konstrukcji.Mogę sobie wyobrazić, że niezwykle naiwny kompilator może generować inny kod maszynowy dla tych dwóch formularzy, przynajmniej po skompilowaniu bez żądania optymalizacji.
Z drugiej strony, kompilatory C absolutnie muszą oceniać niektóre wyrażenia stałe w czasie kompilacji, gdy pojawiają się w kontekstach wymagających wyrażenia stałego. Na przykład:
wymaga diagnostyki; leniwy kompilator nie ma możliwości odroczenia oceny
2+2
do czasu wykonania. Ponieważ kompilator musi mieć możliwość oceny stałych wyrażeń w czasie kompilacji, nie ma dobrego powodu, aby nie korzystać z tej możliwości, nawet jeśli nie jest to wymagane.Tak mówi standard C ( N1570 6.8.5p4)
Odpowiednimi stałymi wyrażeniami są
1 == 0
i2 == 0
oba, które oceniająint
wartość0
. (Te porównania są niejawne w semantycewhile
pętli; nie istnieją jako rzeczywiste wyrażenia C.)Przewrotnie naiwny kompilator mógłby wygenerować inny kod dla obu konstrukcji. Na przykład, dla pierwszego może wygenerować bezwarunkową nieskończoną pętlę (traktując to
1
jako przypadek specjalny), a dla drugiego może wygenerować wyraźne porównanie w czasie wykonywania odpowiadające2 != 0
. Ale nigdy nie spotkałem kompilatora C, który zachowywałby się w ten sposób i poważnie wątpię, czy taki kompilator istnieje.Większość kompilatorów (mam ochotę powiedzieć, że wszystkie kompilatory o jakości produkcyjnej) mają opcje żądania dodatkowej optymalizacji. Przy takiej opcji jest jeszcze mniej prawdopodobne, że kompilator wygeneruje inny kod dla tych dwóch formularzy.
Jeśli Twój kompilator generuje inny kod dla dwóch konstrukcji, najpierw sprawdź, czy różne sekwencje kodu mają różną wydajność. Jeśli tak, spróbuj skompilować ponownie z opcją optymalizacji (jeśli jest dostępna). Jeśli nadal się różnią, prześlij raport o błędzie do dostawcy kompilatora. Nie jest to (koniecznie) błąd w sensie niezgodności ze standardem C, ale prawie na pewno jest to problem, który należy naprawić.
Podsumowując:
while (1)
iwhile(2)
prawie na pewno mają taką samą wydajność. Mają dokładnie taką samą semantykę i żaden kompilator nie ma żadnego powodu, aby nie generować identycznego kodu.I chociaż kompilator generuje szybszy kod dla
while(1)
niż całkowiciewhile(2)
, to równie legalny jest dla kompilatora generowanie szybszego koduwhile(1)
niż dla innego wystąpieniawhile(1)
tego samego programu.(W tym, które zadałeś, kryje się jeszcze jedno pytanie: jak radzisz sobie z ankieterem, który nalega na niewłaściwy punkt techniczny. Prawdopodobnie byłoby to dobre pytanie dla witryny Workplace ).
źródło
while
musi być typu skalarnego, a ciało pętli powtarza się, aż wyrażenie porówna się równe 0. Nie oznacza to, że istnieje domniemanie,expr != 0
które jest oceniane ... które wymagałoby wyniku że - 0 lub 1 - z kolei porównuje się do 0, ad infinitum. Nie, wyrażenie jest porównywane z 0, ale to porównanie nie daje wartości. PS I głosował.<expr> == 0
; To właśnie „porównuje równe 0” środków w C. To porównanie jest częścią semantykiwhile
pętli. Nie ma żadnego znaczenia, ani w standardzie, ani w mojej odpowiedzi, że wynik należy0
ponownie porównać . (Powinienem==
raczej napisać niż!=
.) Ale ta część mojej odpowiedzi była niejasna i zaktualizuję ją.while (2)
,while (pointer)
,while (9.67)
, przez najbardziej naiwnej, niezoptymalizowanych kompilatora, nie będzie widać żadnego kodu wygenerowanego że plony0
lub1
. „Powinienem był napisać == zamiast! =” - nie, to nie miałoby sensu.... == 0
wyrażenia C. Chodzi mi o to, że zarówno „porównania równe 0” wymagane przez opiswhile
pętli standardu, jak i wyraźnex == 0
wyrażenie logicznie implikują tę samą operację. I myślę, że boleśnie naiwny kompilator C może generować kod, który generujeint
wartość0
lub1
dla dowolnejwhile
pętli - chociaż nie sądzę, aby jakikolwiek rzeczywisty kompilator był tak naiwny.Poczekaj minutę. Ankieter, czy wyglądał jak ten facet?
Na tyle źle, że sam ankieter nie zdał tego wywiadu, co jeśli inni programiści w tej firmie „zdali” ten test?
Nie Ocenianie oświadczenia
1 == 0
i2 == 0
powinno być równie szybki. Możemy sobie wyobrazić słabe implementacje kompilatora, w których jedna może być szybsza od drugiej. Ale nie ma dobrego powodu, aby jeden był szybszy od drugiego.Nawet jeśli istnieją jakieś niejasne okoliczności, w których twierdzenie byłoby prawdziwe, programiści nie powinni być oceniani na podstawie wiedzy o niejasnych (aw tym przypadku przerażających) ciekawostkach. Nie martw się o ten wywiad, najlepszym krokiem tutaj jest odejść.
Uwaga: To NIE jest oryginalna kreskówka Dilberta. To jest tylko mashup .
źródło
cmp
operand będzie działał w mniejszej liczbie cykli, porównując 1 do 0 niż 2 do 0? ile cykli zajmuje ogólnie wykonanie cmp? czy jest zmienny zgodnie z wzorami bitowymi? czy są bardziej „złożonymi” wzorcami bitowymi, które spowalniającmp
? Nie wiem osobiście. możesz sobie wyobrazić super idiotyczną implementację sprawdzającą krok po kroku od rangi 0 do n (np. n = 31).cmp
operand powinien być równie szybki dla 1 i 200. Prawdopodobnie moglibyśmy wyobrazić sobie idiotyczne implementacje, w których tak nie jest. Ale czy możemy sobie wyobrazić non-idiotyczną implementację, gdziewhile(1)
jest szybsza niżwhile(200)
? Podobnie, jeśli w jakimś przedhistorycznym wieku jedyna dostępna implementacja była taka idiotyczna, czy powinniśmy dziś o to niepokoić? Nie sądzę, to jest rozmowa szefa ze spiczastymi włosami i to prawdziwy klejnot!Twoje wyjaśnienie jest poprawne. To wydaje się być pytaniem, które oprócz wiedzy technicznej sprawdza Twoją pewność siebie.
Przy okazji, jeśli odpowiedziałeś
powiedziałby ankieter
Odpowiadając tak jak ty, zaoszczędziłeś czas, który w innym przypadku zmarnowałbyś na omawianie tego złego pytania.
Oto przykładowy kod wygenerowany przez kompilator w moim systemie (MS Visual Studio 2012) z wyłączonymi optymalizacjami:
Przy włączonych optymalizacjach:
Tak więc wygenerowany kod jest dokładnie taki sam, przynajmniej z kompilatorem optymalizującym.
źródło
while
długo go poprzedza), a operandwhile
nie jest boolean, _Bool ani żadnego innego określonego typu. Argumentemwhile
może być dowolne wyrażenie ... while załamuje się na 0 i kontynuuje na non-0.while (00000001) {}
nawhile (00000000) {}
. Im więcej prawdziwych bitów, tym mniejsza szansa, że wartość zmieni się na false. Niestety, 2 ma również tylko jeden prawdziwy bit. 3 jednak działałby znacznie dłużej. Dotyczy to również kompilatora, który nie zawsze optymalizuje to (VC ++).Najbardziej prawdopodobnym wyjaśnieniem tego pytania jest to, że ankieter uważa, że procesor sprawdza poszczególne bity liczb, jeden po drugim, aż osiągnie niezerową wartość:
Jeśli „wynosi zero?” algorytm zaczyna się od prawej strony liczby i musi sprawdzać każdy bit, aż osiągnie wartość niezerową,
while(1) { }
pętla musiałaby sprawdzać dwa razy więcej bitów na iterację niżwhile(2) { }
pętla.Wymaga to bardzo błędnego modelu mentalnego działania komputerów, ale ma swoją własną logikę wewnętrzną. Jednym ze sposobów sprawdzenia byłoby pytanie,
while(-1) { }
czywhile(3) { }
byłoby równie szybkie, czy teżwhile(32) { }
byłoby jeszcze wolniejsze .źródło
cmp
algorytm procesora jest liniowym sprawdzaniem bitów z wczesnym wyjściem z pętli na pierwszej różnicy.-O0
dane wyjściowe gcc lub clanga nie są wystarczająco dosłowne”. Nigdy czegoś takiego nie powiedziałem i wcale nie miałem na myśli gcc ani brzęczenia. Musisz mnie źle odczytać. Po prostu nie jestem zdania, że to, co produkuje MSVC, jest przezabawne.while(1)
nie pęka przed pętlą, ale na wyrażeniu. Ale nadal zapada się w pętli podczas optymalizacji ekspresji. Weź ten kod z dużą ilością przerw. Dostajesz to w niezoptymalizowanym trybie debugowania . Podczas optymalizacji wiele punktów przerwania spada razem, a nawet przelewa się do następnej funkcji (IDE pokazuje wynikowe punkty przerwania podczas debugowania) - odpowiedni demontaż .Oczywiście nie znam prawdziwych intencji tego menedżera, ale proponuję zupełnie inny punkt widzenia: zatrudniając nowego członka w zespole, warto wiedzieć, jak reaguje na sytuacje konfliktowe.
Doprowadzili cię do konfliktu. Jeśli to prawda, są sprytni, a pytanie było dobre. W niektórych branżach, takich jak bankowość, opublikowanie problemu w Stack Overflow może być przyczyną odrzucenia.
Ale oczywiście nie wiem, po prostu proponuję jedną opcję.
źródło
Myślę, że wskazówką jest „zapytany przez kierownika wyższego szczebla”. Ta osoba oczywiście przestała programować, kiedy został menadżerem, a potem zajęło jej kilka lat, aby zostać menedżerem wyższego szczebla. Nigdy nie straciłem zainteresowania programowaniem, ale nigdy nie napisałem linii od tamtych czasów. Tak więc jego odniesieniem nie jest „jakikolwiek przyzwoity kompilator”, jak wspomniano w niektórych odpowiedziach, ale „kompilator, z którym ta osoba pracowała 20-30 lat temu”.
W tym czasie programiści spędzili znaczną część czasu na wypróbowywaniu różnych metod zwiększania szybkości i wydajności kodu, ponieważ czas procesora „centralnego minikomputera” był tak cenny. Podobnie jak ludzie piszący kompilatory. Zgaduję, że jedyny kompilator, który jego firma udostępniła w tamtym czasie, zoptymalizowany na podstawie „często spotykanych instrukcji, które można zoptymalizować” i skrócił się na chwilę (1) i wszystko ocenił jeszcze, w tym chwilę (2). Doświadczenie takie mogło wyjaśnić jego pozycję i zaufanie do niego.
Najlepszym sposobem, aby cię zatrudnić, jest prawdopodobnie takie, które pozwala starszemu menedżerowi dać się ponieść emocjom i wygłosić 2-3 minuty na temat „starych dobrych dni programowania”, zanim TY płynnie poprowadzisz go do następnego tematu rozmowy. (Ważny jest tutaj odpowiedni moment - zbyt szybko, a przerywasz historię - zbyt wolno i jesteś oznaczony jako osoba o niewystarczającym skupieniu). Po zakończeniu rozmowy powiedz mu, że chciałbyś dowiedzieć się więcej na ten temat.
źródło
Powinieneś był zapytać go, jak doszedł do tego wniosku. Pod jakimkolwiek przyzwoitym kompilatorem, oba kompilują się do tych samych instrukcji asm. Powinien więc był powiedzieć kompilatorowi, żeby zaczął. Mimo to musiałbyś bardzo dobrze znać kompilator i platformę, aby nawet zgadywać teoretycznie. I w końcu tak naprawdę nie ma to znaczenia w praktyce, ponieważ istnieją inne czynniki zewnętrzne, takie jak fragmentacja pamięci lub obciążenie systemu, które będą miały większy wpływ na pętlę niż ten szczegół.
źródło
Ze względu na to pytanie powinienem dodać, że pamiętam Douga Gwyna z komitetu C, który napisał, że niektóre wczesne kompilatory C bez przepustki optymalizatora wygenerowałyby test zestawu dla
while(1)
(w porównaniu zfor(;;)
którym nie miałby tego).Chciałbym odpowiedzieć ankieterowi, podając tę historyczną notatkę, a następnie powiedzieć, że nawet jeśli byłbym bardzo zaskoczony, że jakikolwiek kompilator to zrobił, kompilator mógłby mieć:
while(1)
iwhile(2)
while(1)
ponieważ są one uważane za idiomatyczne. To zostawiłobywhile(2)
test i dlatego czyni różnicę wydajności między tymi dwoma.Dodałbym oczywiście do ankietera, że nieuwzględnianie
while(1)
iwhile(2)
ten sam konstrukt jest oznaką niskiej jakości optymalizacji, ponieważ są to konstrukty równoważne.źródło
Innym podejściem do takiego pytania byłoby sprawdzenie, czy masz odwagę powiedzieć swojemu przełożonemu, że się myli! I jak delikatnie możesz to przekazać.
Moim pierwszym instynktem byłoby wygenerowanie danych wyjściowych zestawu, aby pokazać menedżerowi, że każdy porządny kompilator powinien się tym zająć, a jeśli tak się nie stanie, prześlesz następną łatkę :)
źródło
Aby zobaczyć, jak wiele osób zagłębia się w ten problem, pokazuje dokładnie, dlaczego może to być test sprawdzający, jak szybko chcesz mikrooptymalizować rzeczy.
Moja odpowiedź brzmiałaby; to nie ma większego znaczenia, wolę skupić się na problemie biznesowym, który rozwiązujemy. W końcu za to otrzymam zapłatę.
Co więcej, wybrałbym,
while(1) {}
ponieważ jest to bardziej powszechne, a inni członkowie drużyny nie musieliby tracić czasu, aby dowiedzieć się, dlaczego ktoś wybrałby liczbę wyższą niż 1.Teraz napisz kod. ;-)
źródło
Jeśli martwisz się optymalizacją, powinieneś użyć
ponieważ to nie ma testów. (tryb cyniczny)
źródło
while(2)
, pozostawia miejsce na optymalizację, a następnie przełączasz się na,for (;;)
gdy jesteś gotowy na zwiększenie wydajności.Wydaje mi się, że jest to jedno z tych pytań podczas wywiadu behawioralnego zamaskowanych jako pytanie techniczne. Niektóre firmy to robią - zadają pytanie techniczne, na które każdy kompetentny programista powinien udzielić dość łatwej odpowiedzi, ale gdy rozmówca udzieli prawidłowej odpowiedzi, ankieter powie im, że się mylą.
Firma chce zobaczyć, jak zareagujesz w tej sytuacji. Czy siedzisz tam cicho i nie naciskasz, że twoja odpowiedź jest prawidłowa z powodu wątpliwości lub strachu przed zdenerwowaniem ankietera? A może chcesz rzucić wyzwanie osobie sprawującej władzę, o której wiesz, że jest w błędzie? Chcą sprawdzić, czy jesteś gotów bronić swoich przekonań i czy możesz to zrobić w taktowny i pełen szacunku sposób.
źródło
Kiedyś programowałem C i kod asemblera z powrotem, gdy ten rodzaj bzdur mógł coś zmienić. Kiedy zrobiło to różnicę, napisaliśmy to na Zgromadzeniu.
Gdybym zadał to pytanie, powtórzyłbym słynny cytat Donalda Knutha z 1974 r. O przedwczesnej optymalizacji i poszedłbym, gdyby rozmówca się nie śmiał i nie ruszył dalej.
źródło
Może osoba przeprowadzająca wywiad celowo zadała takie głupie pytanie i chciała, abyś zrobił 3 punkty:
źródło
Oto problem: jeśli faktycznie piszesz program i mierzysz jego prędkość, prędkość obu pętli może być inna! Dla pewnego rozsądnego porównania:
z dodanym kodem, który drukuje czas, jakiś losowy efekt, taki jak położenie pętli w jednej lub dwóch liniach pamięci podręcznej, może mieć znaczenie. Jedna pętla może przypadkowo znajdować się całkowicie w obrębie jednej linii pamięci podręcznej lub na początku linii pamięci podręcznej, lub może obejmować dwie linie pamięci podręcznej. W rezultacie to, co twierdzi ankieter, jest najszybsze, może faktycznie być najszybsze - przez przypadek.
Scenariusz najgorszego przypadku: Kompilator optymalizacyjny nie wie, co robi pętla, ale stwierdza, że wartości wytworzone podczas wykonywania drugiej pętli są takie same, jak wartości wytworzone przez pierwszą. I wygeneruj pełny kod dla pierwszej pętli, ale nie dla drugiej.
źródło
Oba są równe - to samo.
Zgodnie ze specyfikacjami wszystko, co nie jest 0, jest uważane za prawdziwe, więc nawet bez jakiejkolwiek optymalizacji, a dobry kompilator nie wygeneruje żadnego kodu dla while (1) lub while (2). Kompilator wygeneruje proste sprawdzenie
!= 0
.źródło
Sądząc po ilości czasu i wysiłku, jaki ludzie spędzili na testowaniu, udowadnianiu i odpowiadaniu na to bardzo proste pytanie, twierdzę, że obaj spóźnili się, zadając to pytanie.
Aby spędzić na tym jeszcze więcej czasu ...
„while (2)” jest śmieszne, ponieważ,
„while (1)” i „while (true)” są historycznie używane do tworzenia nieskończonej pętli, która oczekuje, że „przerwa” zostanie wywołana na pewnym etapie wewnątrz pętli w oparciu o warunek, który z pewnością wystąpi.
„1” jest po prostu po to, aby zawsze oceniać na prawdę, a zatem powiedzenie „while (2)” jest tak samo głupie, jak powiedzenie „while (1 + 1 == 2)”, które również będzie oceniać na true.
A jeśli chcesz być całkowicie głupi, po prostu użyj:
Chciałbym pomyśleć, że twój programista napisał literówkę, która nie wpłynęła na działanie kodu, ale jeśli celowo użył „2” tylko po to, by być dziwnym, to spuść go, zanim wprowadzi dziwny sh! T przez cały kod, co utrudnia czytać i pracować z.
źródło
To zależy od kompilatora.
Jeśli zoptymalizuje kod lub jeśli oceni 1 i 2 na wartość true przy użyciu tej samej liczby instrukcji dla określonego zestawu instrukcji, szybkość wykonywania będzie taka sama.
W rzeczywistych przypadkach zawsze będzie tak samo szybko, ale można by sobie wyobrazić konkretnego kompilatora i konkretnego systemu, gdyby był on oceniany inaczej.
Mam na myśli: tak naprawdę nie jest to pytanie związane z językiem (C).
źródło
Ponieważ ludzie, którzy chcą odpowiedzieć na to pytanie, chcą najszybszej pętli, odpowiedziałbym, że oba kompilują się w tym samym kodzie asemblera, jak podano w innych odpowiedziach. Niemniej jednak możesz zasugerować ankieterowi za pomocą „rozwijania pętli”; pętla do {} while zamiast pętli while.
Ostrożnie: musisz upewnić się, że pętla przynajmniej raz uruchomi się raz .
Pętla powinna mieć stan pęknięcia w środku.
Również dla tego rodzaju pętli osobiście wolałbym używać do {} while (42), ponieważ każda liczba całkowita, z wyjątkiem 0, wykonałaby zadanie.
źródło
Oczywista odpowiedź brzmi: jak napisano, oba fragmenty uruchomiłyby równie zajętą nieskończoną pętlę, co czyni program nieskończenie wolnym .
Chociaż redefiniowanie słów kluczowych C jako makr technicznie miałoby nieokreślone zachowanie, jest to jedyny sposób, w jaki mogę wymyślić szybki fragment fragmentu kodu: możesz dodać ten wiersz powyżej 2 fragmentów:
rzeczywiście będzie
while(1)
dwa razy szybszy (lub o połowę wolniejszy) niżwhile(2)
.źródło
Jedyny powód, dla którego mogę wymyślić, dlaczego
while(2)
byłoby wolniej, to:Kod optymalizuje pętlę do
cmp eax, 2
Kiedy następuje odejmowanie, zasadniczo odejmujesz
za.
00000000 - 00000010 cmp eax, 2
zamiast
b.
00000000 - 00000001 cmp eax, 1
cmp
ustawia tylko flagi i nie ustawia wyniku. Więc na najmniej znaczących bitach wiemy, czy musimy pożyczyć, czy nie za pomocą b . Podczas gdy przy pomocy musisz wykonać dwa odejmowania, zanim otrzymasz pożyczkę.źródło