Moje pytanie dotyczy linii, o której wspomniałem w temacie i którą widzę w wielu miejscach w kodzie produkcyjnym.
Ogólny kod wygląda następująco:
if (0) {
// Empty braces
} else if (some_fn_call()) {
// actual code
} else if (some_other_fn_call()) {
// another actual code
...
} else {
// default case
}
Inne gałęzie są nieistotne dla mojego pytania. Zastanawiam się, jakie jest znaczenie wstawiania if (0)
tutaj. Nawiasy są puste, więc nie sądzę, że ma komentować jakiś blok kodu. Czy zmusza kompilator do optymalizacji, czy też ma inne intencje?
Próbowałem poszukać tego wyraźnego przypadku tutaj w SO iw Internecie, ale bezskutecznie. Są podobne pytania dotyczące JavaScript, ale nie C. Jest jeszcze jedno pytanie: Co się stanie, gdy zero zostanie przypisane w warunku „if”? , ale omawia przypisanie zerowe do zmiennej, a nie samo użycie „if (0)”.
c
if-statement
Zzaponka
źródło
źródło
Odpowiedzi:
Czasami używam tego do symetrii, więc mogę
else if{
swobodnie poruszać drugim edytorem, nie myśląc o pierwszymif
.Semantycznie
część nic nie robi i możesz liczyć na optymalizatory, które ją usuną.
źródło
if else
prefiks do wszystkich znaczących ścieżek kodu ładnie dopełnia warunki i ułatwia ich skanowanie. (Jest to jednak subiektywne i zależałoby w dużej mierze od tego, co naprawdę znajduje się w warunkach i blokach kodu).if (0) {..}
wprowadzał jakikolwiek problem z parsowaniem / czytelnością. Powinno to być oczywiste dla każdego, kto trochę zna C. To nie jest problem. Problemem jest pytanie uzupełniające po przeczytaniu: „Po co to do diabła jest?” O ile nie jest to do celów debugowania / tymczasowych (tj. Intencją jest „włączenie” tegoif
bloku później), zalecałbym całkowite usunięcie . Zasadniczo „czytanie” takiego kodu prawdopodobnie spowodowałoby niepotrzebną „pauzę” dla czytelnika bez dobrego powodu. I to wystarczający powód, aby go usunąć.else if
się po edytorze bez obaw”, ponieważ warunki mogą się nie wykluczać, w takim przypadku kolejność ma znaczenie. Osobiście użyłbym tylkoif
i wykonałbym wczesny powrót , wyodrębniając łańcuch logiczny do oddzielnej funkcji, jeśli to konieczne.Może to być przydatne, jeśli istnieją
#if
oświadczenia, alaitp.
W takim przypadku każdy (i wszystkie) z testów można
#if
usunąć, a kod zostanie poprawnie skompilowany. Prawie wszystkie kompilatory usuną tęif (0) {}
część. Prosty autogenerator mógłby wygenerować taki kod, ponieważ jest nieco łatwiejszy do zakodowania - nie musi oddzielnie uwzględniać pierwszego włączonego bloku.źródło
if
/else if
nie jest używany tak często jako drzewo decyzyjne, ale raczej jako konstrukcja „działaj po pierwszym dopasowaniu warunku”, gdzie warunek mający najwyższy priorytet nie jest szczególnie „specjalny”. Chociaż nie widziałem tegoif(0)
jako sposobu, aby wszystkie prawdziwe gałęzie miały spójną składnię, podoba mi się spójna składnia, którą ułatwia.else if
linię na dwie i umieść między nimi ochronę preprocesora.if (0)
gałąź i sformatowałbym resztę tak, abyelse
była na własnej linii, otoczona strażnikiem wzdłuż linii#if TEST1_ENABLED && TEST2_ENABLED
.Widziałem podobny wzorzec używany w wygenerowanym kodzie. Na przykład w SQL widziałem biblioteki emitujące następującą
where
klauzulę.Prawdopodobnie ułatwia to po prostu dodanie innych kryteriów, ponieważ wszystkie dodatkowe kryteria można poprzedzić
and
zamiast dodatkowego sprawdzenia, czy jest to pierwsze kryterium, czy nie.źródło
1=1
Jest „przydatna”, ponieważ zawsze można dodaćwhere
z przodu, bezwarunkowo. W przeciwnym razie musisz sprawdzić, czy jest pusty, a jeśli tak, unikaj generowaniawhere
klauzuli.1=1
zWHERE
pliku, więc nie ma to wpływu na wydajność.Jak napisano,
if (0) {}
klauzula kompiluje się do zera.Podejrzewam, że funkcja klauzuli na szczycie tej drabiny jest zapewnienie łatwego miejsce tymczasowe wyłączenie wszystkich innych funkcji na raz (dla celów porównawczych debugowania lub) zmieniając
0
Do1
lubtrue
.źródło
Nie jestem pewien żadnych optymalizacji, ale moje dwa centy:
Stało się tak z powodu pewnej modyfikacji kodu, w której usunięto jeden podstawowy warunek (
if
powiedzmy wywołanie funkcji w bloku początkowym ), ale programiści / opiekunowieif-else
blokwięc zamiast usuwać powiązany
if
blok, po prostu zmienili warunek naif(0)
i ruszyli dalej.źródło
if(0)
zmniejsza też zasięgu oddziałów?To gnicie kodu.
W pewnym momencie, że „jeśli” zrobiło coś pożytecznego, sytuacja się zmieniła, być może oceniana zmienna została usunięta.
Osoba, która naprawiała / zmieniała system, w jak najmniejszym stopniu wpływała na logikę systemu, więc po prostu upewniła się, że kod zostanie ponownie skompilowany. Więc zostawia „jeśli (0)”, ponieważ jest to szybkie i łatwe i nie jest do końca pewien, czy tego chce. Sprawia, że system działa i nie wraca, aby go całkowicie naprawić.
Następnie przychodzi następny programista i uważa, że zostało to zrobione celowo i komentuje tylko tę część kodu (ponieważ i tak nie jest ona oceniana), a następnym razem, gdy kod zostanie dotknięty, te komentarze są usuwane.
źródło
Jedna możliwość, o której jeszcze nie wspomniano:
if (0) {
linia mogłaby stanowić dogodne miejsce na punkt przerwania.Debugowanie jest często wykonywane na niezoptymalizowanym kodzie, więc zawsze fałszywy test będzie obecny i będzie mógł mieć ustawiony na nim punkt przerwania. Po skompilowaniu do produkcji linia kodu zostanie zoptymalizowana. Pozornie bezużyteczna linia zapewnia funkcjonalność do programowania i testowania kompilacji bez wpływu na kompilacje wydań.
Powyżej znajdują się również inne dobre sugestie; jedynym sposobem, aby naprawdę wiedzieć, jaki jest cel, jest wyśledzenie autora i zapytanie. Twój system kontroli kodu źródłowego może w tym pomóc. (Poszukaj
blame
funkcji typu -type).źródło
Widziałem nieosiągalne bloki kodu we wstępnie rozwiniętym JavaScript, które zostały wygenerowane przy użyciu języka szablonów.
Na przykład kod, który czytasz, mógł zostać wklejony z serwera, który wstępnie oceniał pierwszy warunek, który w tym czasie opierał się na zmiennej dostępnej tylko po stronie serwera.
które kiedyś wstępnie skompilowano:
Mam nadzieję, że pomoże ci to w relatywizacji potencjalnego niskiego poziomu aktywności klawiatury w erze pro-recyklingowych programistów, dla której przejawiam entuzjazm!
źródło
Konstrukcja ta może być również używana w C do implementacji programowania ogólnego z bezpieczeństwem typów, opierając się na fakcie, że nieosiągalny kod jest nadal sprawdzany przez kompilator:
źródło
Myślę, że to po prostu zły kod. Pisząc szybki przykład w Compiler Explorer, widzimy, że zarówno w gcc, jak i clang nie jest generowany żaden kod dla
if (0)
bloku, nawet przy całkowicie wyłączonych optymalizacjach:https://godbolt.org/z/PETIks
Zabawa z usuwaniem
if (0)
przyczyn nie powoduje żadnych zmian w wygenerowanym kodzie, więc dochodzę do wniosku, że nie jest to optymalizacja.Możliwe, że kiedyś było coś w górnym
if
bloku, co zostało później usunięte. Krótko mówiąc, wygląda na to, że usunięcie go spowodowałoby wygenerowanie dokładnie tego samego kodu, więc możesz to zrobić.źródło
Jak już powiedziano, zero jest oceniane jako fałszywe, a gałąź prawdopodobnie zostanie zoptymalizowana przez kompilator.
Widziałem to również wcześniej w kodzie, w którym dodano nową funkcję i potrzebny był wyłącznik awaryjny (jeśli coś pójdzie nie tak z funkcją, możesz ją po prostu wyłączyć), a jakiś czas później, gdy wyłącznik awaryjny został usunięty, programista nie usunął też gałęzi, np
stał się
źródło
Pomaga zdebugować ten blok, po prostu wstawiając blok 1. To wyłącza wszystkie funkcje if else block. Możemy również rozszerzyć blok if else.
źródło
źródło
@ PSkocik odpowiedź jest w porządku, ale dodaję moje dwa centy. Nie jestem pewien, czy powinienem to zrobić jako komentarz, czy jako odpowiedź; wybierając to drugie, ponieważ IMHO jest warte zobaczenia przez innych, podczas gdy komentarze są często niewidoczne.
Nie tylko czasami używam
Ale czasami to robię
lub
dla skomplikowanych warunków. Z tych samych powodów - łatwiejsza edycja, #ifdef itp.
Jeśli o to chodzi, w Perlu zrobię
Porównuję
if(0)
kod do seplenieniaktóry, jak się domyślacie, mogę wcisnąć jako
Czasami próbowałem sobie wyobrazić, jak mogłaby wyglądać bardziej czytelna dla człowieka składnia.
Być może
zainspirowany [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if][Guarded Command Language]] od Dikstry .
Ale ta składnia implikuje, że warunki są oceniane równolegle, podczas gdy
if...else-if
implikuje sekwencyjną i priorytetową ocenę warunków.Zacząłem robić tego typu rzeczy, pisząc programy, które generowały inne programy, gdzie jest to szczególnie wygodne.
Skoro już o tym mowa, pisząc RTL przy użyciu starego iHDL Intela, zakodowałem takie rzeczy jak
gdzie
FORC..DOC..ENDC
jest konstrukcją pętli preprocesora makra, która rozwija się doTo było pojedyncze przypisanie, niewymagający, kod, więc ustawienie zmiennej stanu nie było dozwolone, jeśli trzeba było wykonać takie czynności, jak znalezienie pierwszego ustawionego bitu.
Jeśli się nad tym zastanowić, to mogło być pierwsze miejsce, w którym zetknąłem się z takimi konstrukcjami.
Przy okazji, zastrzeżenia, które niektórzy mieli do stylu if (0) - że warunki else-if są sekwencyjnie zależne i nie można ich dowolnie zmieniać - nie dotyczą logiki AND i OR oraz XOR w RTL - ale mają zastosowanie do obwód && i ||.
źródło
Widziałem, że jest to używane na przykład do obsługi błędów
Może to być pomocne, gdy do zarządzania błędami używa się goto, instrukcje są wykonywane tylko wtedy, gdy wystąpi błąd. Widziałem to w bardzo starym kodzie C (gdzie argumenty funkcji są zapisywane poza '()'), nie sądzę, żeby ktokolwiek teraz to śledził.
źródło
Widziałem to kilka razy, myślę, że najbardziej prawdopodobnym powodem jest ocena czegoś w starszej / innej wersji / gałęzi kodu lub być może w celu debugowania i zmiana tego na
if(0)
jest nieco leniwym sposobem usuwania tego, co tam było .źródło