Meine Frage bezieht sich auf die Zeile, die ich im Betreff erwähnt habe und die ich an vielen Stellen im Produktionscode sehen kann.
Der Gesamtcode sieht folgendermaßen aus:
if (0) {
// Empty braces
} else if (some_fn_call()) {
// actual code
} else if (some_other_fn_call()) {
// another actual code
...
} else {
// default case
}
Die anderen Zweige sind für meine Frage irrelevant. Ich frage mich, was es bedeutet, if (0)
hier zu setzen . Die geschweiften Klammern sind leer, daher denke ich nicht, dass sie einen Codeblock kommentieren sollen. Erzwingt es den Compiler, eine Optimierung vorzunehmen, oder unterscheiden sich seine Absichten?
Ich habe versucht, diesen expliziten Fall hier auf SO und im Internet zu suchen, aber ohne Erfolg. Es gibt ähnliche Fragen zu JavaScript, aber nicht zu C. Es gibt eine andere Frage: Was passiert, wenn eine Null in einer Wenn-Bedingung zugewiesen wird? Es wird jedoch die Zuweisung von Null zu einer Variablen erörtert, nicht die Verwendung von 'if (0)' selbst.
quelle
Antworten:
Ich benutze dies manchmal aus Symmetriegründen, damit ich den anderen
else if{
mit meinem Editor frei bewegen kann, ohne auf den ersten achten zu müssenif
.Semantisch die
Teil macht nichts und Sie können sich darauf verlassen, dass Optimierer es löschen.
quelle
if else
Präfix für alle wichtigen Codepfade die Bedingungen gut ausrichtet und das Scannen erleichtert. (Das ist jedoch subjektiv und würde viel davon abhängen, was wirklich in den Bedingungen und Codeblöcken enthalten ist.)if (0) {..}
dass es Probleme mit der Parsierbarkeit / Lesbarkeit gibt. Es sollte jedem klar sein, der ein bisschen von C weiß. Das ist kein Problem. Das Problem ist die Folgefrage nach dem Lesen: "Wofür zum Teufel ist es dann?" Sofern es sich nicht um Debugging- / temporäre Zwecke handelt (dh die Absicht besteht darin, diesenif
Block später zu "aktivieren" ), würde ich empfehlen , ihn insgesamt zu entfernen . Grundsätzlich würde das "Lesen" eines solchen Codes ohne guten Grund wahrscheinlich eine unnötige "Pause" für den Leser verursachen. Und das ist Grund genug, es zu entfernen.else if
ohne Sorgen im Editor bewegen können", da sich die Bedingungen möglicherweise nicht gegenseitig ausschließen. In diesem Fall ist die Reihenfolge wichtig. Persönlich würde ich nur verwendenif
und eine frühzeitige Rückkehr durchführen und die Logikkette bei Bedarf in eine separate Funktion extrahieren.Dies kann nützlich sein, wenn es
#if
Aussagen gibt, alaetc.
In diesem Fall können alle (und alle) Tests
#if
gelöscht werden, und der Code wird korrekt kompiliert. Fast alle Compiler entfernen dasif (0) {}
Teil. Ein einfacher Autogenerator könnte Code wie diesen generieren, da er etwas einfacher zu codieren ist - er muss den ersten aktivierten Block nicht separat betrachten.quelle
if
/else if
Kette nicht so sehr als Entscheidungsbaum verwendet, sondern als Konstrukt "Auf die erste übereinstimmende Bedingung einwirken", bei dem die Bedingung mit der höchsten Priorität nicht besonders "speziell" ist. Ich hatte zwar nicht gesehenif(0)
, dass alle realen Zweige eine konsistente Syntax haben, aber ich mag die konsistente Syntax, die sie ermöglicht.else if
Linie in zwei Teile und setzen Sie den Präprozessorschutz dazwischen.if (0)
Zweig entfernen und den Rest so neu formatieren, dass erelse
sich in einer eigenen Zeile befindet, umgeben von einer Wache nach dem Vorbild von#if TEST1_ENABLED && TEST2_ENABLED
.Ich habe ein ähnliches Muster gesehen, das im generierten Code verwendet wird. In SQL habe ich beispielsweise gesehen, dass Bibliotheken die folgende
where
Klausel ausgeben .Dies erleichtert vermutlich das Hinzufügen anderer Kriterien, da allen zusätzlichen Kriterien
and
anstelle einer zusätzlichen Prüfung vorangestellt werden kann, ob es sich um das erste Kriterium handelt oder nicht.quelle
1=1
ist auch "nützlich", weil Sie daswhere
vorne immer bedingungslos hinzufügen können . Andernfalls müssten Sie überprüfen, ob es leer ist, und in diesem Fall vermeiden, diewhere
Klausel zu generieren .1=1
aus demWHERE
, sodass es keinen Einfluss auf die Leistung hat.Wie geschrieben,
if (0) {}
kompiliert die Klausel zu nichts.Ich vermute, dass die Funktion der Klausel oben auf dieser Leiter darin besteht, einen einfachen Ort bereitzustellen, an dem alle anderen Funktionen auf einmal vorübergehend deaktiviert werden können (zu Debugging- oder Vergleichszwecken), indem
0
in a1
oder geändert wirdtrue
.quelle
Ich bin mir keiner Optimierung sicher, aber meine zwei Cent:
Dies geschah aufgrund einer Codeänderung, bei der eine Hauptbedingung entfernt wurde (der Funktionsaufruf im Anfangsblock
if
, sagen wir), aber die Entwickler / Betreuerif-else
Block umzustrukturierenAnstatt den zugehörigen
if
Block zu entfernen , änderten sie einfach die Bedingung inif(0)
und gingen weiter.quelle
if(0)
Verringert sich nicht auch die Filialabdeckung?Es ist Code Rot.
Irgendwann, als "wenn" etwas Nützliches tat, änderte sich die Situation, möglicherweise wurde die zu bewertende Variable entfernt.
Die Person, die das System reparierte / änderte, tat so wenig wie möglich, um die Logik des Systems zu beeinflussen , und stellte nur sicher, dass der Code neu kompiliert wurde. Also hinterlässt er ein "if (0)", weil das schnell und einfach geht und er nicht ganz sicher ist, ob er das tun möchte. Er bringt das System zum Laufen und geht nicht zurück, um es vollständig zu reparieren.
Dann kommt der nächste Entwickler und denkt, dass dies absichtlich gemacht wurde und kommentiert nur diesen Teil des Codes aus (da er sowieso nicht ausgewertet wird). Wenn der Code das nächste Mal berührt wird, werden diese Kommentare entfernt.
quelle
Eine noch nicht erwähnte Möglichkeit: Die
if (0) {
Linie könnte einen geeigneten Ort für einen Haltepunkt bieten.Das Debuggen wird häufig für nicht optimierten Code durchgeführt, sodass der immer falsche Test vorhanden ist und ein Haltepunkt festgelegt werden kann. Bei der Kompilierung für die Produktion würde die Codezeile optimiert. Die scheinbar nutzlose Zeile bietet Funktionen zum Entwickeln und Testen von Builds, ohne die Release-Builds zu beeinträchtigen.
Es gibt auch andere gute Vorschläge oben; Der einzige Weg, um wirklich zu wissen, was der Zweck ist, besteht darin, den Autor aufzuspüren und zu fragen. Ihr Quellcode-Kontrollsystem könnte dabei helfen. (Suchen Sie nach
blame
Funktionen vom Typ.)quelle
Ich habe nicht erreichbare Codeblöcke in vorerweitertem JavaScript gesehen, die mit einer Vorlagensprache generiert wurden.
Beispielsweise könnte der Code, den Sie lesen, von einem Server eingefügt worden sein, der die erste Bedingung vorab ausgewertet hat, die zu diesem Zeitpunkt auf einer Variablen beruhte, die nur auf der Serverseite verfügbar war.
die einmal vorkompilierte Hences:
Ich hoffe, dies hilft Ihnen dabei, die potenziell niedrige Tastaturaktivität der Pro-Recycling-Codierer-Ära zu relativieren, für die ich Begeisterung zeige!
quelle
Dieses Konstrukt kann auch in C verwendet werden, um generische Programmierung mit Typensicherheit zu implementieren, wobei davon ausgegangen wird, dass der nicht erreichbare Code noch vom Compiler überprüft wird:
quelle
Ich denke, es ist nur schlechter Code. Wenn wir ein kurzes Beispiel im Compiler-Explorer schreiben, sehen wir, dass sowohl in gcc als auch in clang kein Code für den
if (0)
Block generiert wird , selbst wenn die Optimierungen vollständig deaktiviert sind:https://godbolt.org/z/PETIks
Das Herumspielen mit dem Entfernen der
if (0)
Ursachen führt zu keinen Änderungen am generierten Code, daher komme ich zu dem Schluss, dass dies keine Optimierung ist.Es ist möglich, dass sich im oberen
if
Block etwas befand, das später entfernt wurde. Kurz gesagt, es sieht so aus, als würde durch das Entfernen genau derselbe Code generiert. Sie können dies also jederzeit tun.quelle
Wie bereits erwähnt, wird die Null als falsch ausgewertet, und der Zweig wird wahrscheinlich vom Compiler optimiert.
Ich habe dies auch schon einmal in Code gesehen, in dem eine neue Funktion hinzugefügt wurde und ein Kill-Schalter benötigt wurde (wenn etwas mit der Funktion schief geht, können Sie sie einfach ausschalten), und einige Zeit später, als der Kill-Schalter entfernt wurde Der Programmierer hat den Zweig nicht entfernt, z
wurden
quelle
Es ist hilfreich, diesen Block zu debuggen, indem nur if 1 gesetzt wird. Dadurch wird die Blockfunktionalität deaktiviert. Und wir können auch den if else-Block erweitern.
quelle
quelle
@ PSkociks Antwort ist in Ordnung, aber ich addiere meine zwei Cent. Unsicher, ob ich dies als Kommentar oder als Antwort tun soll; Wählen Sie Letzteres, weil IMHO andere sehenswert sind, während Kommentare häufig unsichtbar sind.
Ich benutze nicht nur gelegentlich
Aber ich mache es auch gelegentlich
oder
für komplizierte Bedingungen. Aus den gleichen Gründen - einfacher zu bearbeiten, #ifdef usw.
Im Übrigen werde ich in Perl tun
Ich vergleiche den
if(0)
Code mit lispwas, Sie haben es erraten, ich kann einrücken als
Ich habe manchmal versucht mir vorzustellen, wie eine besser lesbare Syntax dafür aussehen könnte.
Vielleicht
inspiriert von Dikstras [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if‹[Guarded Command Language].
Diese Syntax impliziert jedoch, dass die Bedingungen parallel ausgewertet werden, während
if...else-if
die sequentielle und priorisierte Bewertung der Bedingungen impliziert wird.Ich habe so etwas angefangen, als ich Programme geschrieben habe, die andere Programme generiert haben, wo es besonders praktisch ist.
Während wir gerade dabei sind, RTL mit Intels alter iHDL zu schreiben, habe ich Sachen wie codiert
Dabei
FORC..DOC..ENDC
handelt es sich um ein Makro-Präprozessor-Schleifenkonstrukt, das auf erweitert wirdDies war eine nicht zwingende Einzelzuweisung, daher war das Festlegen einer Statusvariablen nicht zulässig, wenn Sie beispielsweise das erste gesetzte Bit suchen mussten.
Wenn ich daran denke, war dies vielleicht der erste Ort, an dem ich auf solche Konstrukte gestoßen bin.
Übrigens gelten die Einwände, die einige gegen den if (0) -Stil hatten - dass die else-if-Bedingungen sequentiell abhängig sind und nicht willkürlich neu angeordnet werden können - nicht für die AND- und OR- und XOR-Logik in RTL - sondern für Short- Schaltung && und ||.
quelle
Ich habe gesehen, dass dies zum Beispiel zur Behandlung von Fehlern verwendet wurde
Dies kann hilfreich sein, wenn goto zum Verwalten von Fehlern verwendet wird. Anweisungen werden nur ausgeführt, wenn ein Fehler auftritt. Ich habe dies in sehr altem C-Code gesehen (wo Funktionsargumente außerhalb von '()' geschrieben sind), glaube nicht, dass jetzt jemand dem folgt.
quelle
Ich habe dies einige Male gesehen. Ich denke, der wahrscheinlichste Grund ist, dass etwas in einer älteren / anderen Version / einem anderen Zweig des Codes ausgewertet oder möglicherweise zum Debuggen verwendet wurde. Das Ändern in
if(0)
ist eine etwas träge Methode, um alles zu entfernen, was vorhanden war .quelle