Warum ist diese version logischer UND in C nicht zeigen, Kurzschluss-Verhalten?
Ja, das ist eine Hausaufgaben-Frage, aber ich habe meine Forschung getan und einen fairen Betrag von tiefen Gedanken über das Thema und können nicht dies herauszufinden. Die Frage besagt, dass dieses Stück code NICHT aufweisen Kurzschluss-Verhalten und fragt, warum. Aber es sieht für mich, wie es Ausstellung Kurzschluss-Verhalten, so kann sich das jemand erklären warum nicht?
In C:
int sc_and(int a, int b) {
return a ? b : 0;
}
Sieht es für mich aus, dass in dem Fall, dass a
ist false, das Programm wird nicht versuchen, Sie zu bewerten b
an alle, aber ich muss falsch sein. Warum tut das Programm auch nur zu berühren b
in diesem Fall, wenn Sie nicht haben, um?
- Wie ist typisch für die meisten künstlich Hausaufgaben Fragen, du wirst nie sehen diese Art von code in ein Produktivsystem, es sei denn, der Programmierer ist, absichtlich zu versuchen, clever zu sein.
- Du wirst sehen, der code genau so in production systems-alle Zeit! Es ist nicht wahrscheinlich, um eine Funktion mit dem Namen
AND()
, aber die Funktionen empfangen von Argumenten nach Wert und dann bewerten Sie (oder nicht) abhängig von der Logik der Funktion, die überall zu finden sind. Trotz des seins eine "Fangfrage", es ist eine kritische Verhalten von C zu verstehen. In einer Sprache, die mit call-by-name würde diese Frage eine ganz andere Antwort. - Ich war kommentieren Sie den code, nicht das Verhalten. Ja, Sie müssen verstehen, das Verhalten. Nein, Sie brauchen nicht, um code zu schreiben wie dieses.
- Das ist eigentlich schon ziemlich relevant, wenn Sie einmal die code in VB und Begegnung IIf. Denn es ist eine Funktion eher als ein operator die Evaluierung wird nicht kurzgeschlossen. Dies kann zu Problemen für die Entwickler benutzt, um die Kurzschluss-operator, der dann Sachen schreiben wie
IIf(x Is Nothing, Default, x.SomeValue)
. - weil es ein Armutszeugnis für das Bildungssystem.
- VB hat exakt diese Funktion, genannt IIf. Wir hatten schon ein paar "Ingenieure", die nicht heraus, dass beide Seiten der IIf wurden ausgewertet.
- Bei Verwendung von Funktionszeigern und überlast für jede option; (bool,bool / bool "fun / Spaß", "bool" / Spaß,Spaß), wäre es dann möglich? gewährt, du würdest die Funktion Zeiger etc im Ausdruck nicht die Funktion selbst, sondern (zwar künstlich) konnte ich sehen, dass es funktioniert.
- Diese Frage macht mich froh, dass ich fertig bin mit der Schule. 🙂
- Streng, weder int, 'a' noch 'b' wird 'false', da kein solcher Wert existiert in C. haben Sie zwei int-Werte. Sie beide müssen kopiert werden? Ich nehme an, Sie würden schauen müssen, um den standard zu sehen, ob die Auswertung von 'b' könnte kurzgeschlossen werden. Es scheint, dass eine Laufzeit-Optimierung könnte überspringen Sie die Bewertung "b". Es würde bedeuten, re-ordering code im Aufrufer zu tun, wenn es feststellen könnte, dass " b " nicht notwendig war, auf den Stapel.
- falsch und wahr in C sind Sätze, nicht um Werte. Insbesondere stimmt die Menge aller nicht-null-Werte. Sie müssen true und false werden in der Lage zu tun, Boolesche Logik, und niemand leugnet Sie tun können, Boolesche Logik in C. Als für das überspringen
b
ist die Bewertung zwingend für die beobachtbaren Nebenwirkungen (nur). - Der ternäre operator nicht Kurzschluss. Sie können dies testen, indem Sie ersetzen
a
undb
mit Funktionen, die umfassen Nebenwirkungen. Beispiel: ideone.com/WHIS2v - Es ist erwähnenswert, dass, zusätzlich zu den Mangel an Kurzschluss-Verhalten, das
sc_and
- Funktion ist nicht äquivalent zu der&&
Betreiber.sc_and(2, 3)
Erträge 3;2&&3
Erträge 1. (Das Ergebnis hat die gleiche Wahrheit Wert, aber.)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist eine Fangfrage.
b
ist ein input-argument für diesc_and
Methode, und so werden immer ausgewertet. In anderen Wortensc_and(a(), b())
rufena()
- und call -b()
(Reihenfolge nicht garantiert), dann rufen Siesc_and
mit den Ergebnissen dera(), b()
die Pässe zua?b:0
. Es hat nichts zu tun mit dem ternären operator selbst, die absolut Kurzschluss.UPDATE
Mit Bezug auf, warum ich nannte dies einen "Stich-Frage": ist Es, weil der Mangel an gut definierten Rahmen für, wo zu erwägen 'Kurzschluss' (zumindest so, wie wiedergegeben durch die OP). Viele Personen, wenn da nur die definition einer Funktion davon ausgehen, dass der Kontext der Frage ist die Frage nach der Körper der Funktion; Sie oft berücksichtigen nicht die Funktion als Ausdruck in und von sich selbst. Dies ist der "trick" der Frage; um Sie daran Zu erinnern, dass in der Programmierung im Allgemeinen, aber besonders in Sprachen wie C-mag, die haben oft viele Ausnahmen zu Regeln, können Sie nicht tun. Beispiel, wenn die Frage als solche:
Wäre es sofort klar, dass man eigentlich denken
sc_and
als ein operator in und von sich selbst in Ihrem eigenen domain-spezifische Sprache, und die Bewertung, ob die Aufrufsc_and
Exponate Kurzschluss Verhalten wie eine normale&&
würde. Ich würde nicht halten, das ist eine Fangfrage, denn es ist klar, dass man eigentlich nicht, um den Fokus auf die ternären operator, und sind stattdessen soll der Fokus auf C/C++ " s-Funktion-call-Mechaniker (und ich würde vermuten, führen schön in einer follow-up-Frage zum schreiben einessc_and
das bedeutet Kurzschluss, was würde mit einem#define
eher als eine Funktion).Ob oder nicht Sie anrufen, was der ternäre operator selbst nicht kurzschließen (oder etwas anderes, wie "bedingte Bewertung") hängt von Ihrer definition des Kurzschlusses, und Lesen Sie die verschiedenen Kommentare zu Gedanken auf, die. Von mir es tut, aber es ist nicht sehr relevant für die eigentliche Frage oder warum ich nannte es einen "trick".
?
, wie inif (condition) {when true} else {when-false}
. Das ist nicht genannt Kurzschluss.x Sand y
(mit Sand, um die Kurzschluss-Sorte) entspricht dem bedingten Ausdruckif x then y else false;
den Ausdruckx Sor y
entsprichtif x then true else y
..if(a()) return b(); return false;
"kurze circuts" trotz der Tatsache, es ist semantisch identisch zureturn a() && b();
a
.afun(side_effects(), side_effects2())
ich selten wollen afun zu drehen und NICHT bewerten, diese Argumente! (natürlich ist dies sehr wahr in C und in Wahrheit nicht so wirklich in funktionalen Sprachen)&&
und||
Kurzschluss. Wenn Sie anrufen?:
kurze circuitnig Sie hätte anrufenif()
Kurzschluss, da?:
ist nur syntaktischer Zucker für einif
.if else
, nicht einif
. Und selbst dann ist es nicht wirklich; der?:
Betreiber ist die expressionif-else
ist ein - Anweisung in. Diese sind semantisch sehr unterschiedliche Dinge, auch wenn Sie konstruieren eine entsprechende Reihe von Aussagen und das erzeugt den gleichen Effekt wie der ternäre expression. Dies ist der Grund, warum es als Kurzschluss, die meisten anderen Ausdrücke immer bewerten alle Ihre Operanden (+,-,*,/
etc). Wenn Sie nicht, es ist ein Kurzschluss (&&, ||
).?:
Betreiber passt diese definition.if-else
ist kein Betreiber.if else
".Wenn die Anweisung
führt,
b++
wird nicht ausgewertet, wenn der operanda
ausgewertet, umfalse
(Kurzschluss-Verhalten). Dies bedeutet, dass die Nebenwirkung aufb
wird nicht stattfinden.Betrachten Sie nun die Funktion:
bezeichnen
In diesem Fall, ob
a
isttrue
oderfalse
,b++
wird immer evaluiert werden beim Funktionsaufruf und Nebenwirkung aufb
wird immer stattfinden.Gleiche gilt für
und
int x = a ? b++ : 0
als beobachtbare Kurzschluss.Wie bereits von anderen darauf hingewiesen wird, egal, was wird passieren in der Funktion als zwei Argumente, es wird ausgewertet, wie wird es weitergegeben. Das ist Weg, bevor das tenary Betrieb.
Auf der anderen Seite, diese
würde "Kurzschluss", da diese makro bedeutet nicht, dass eine Funktion aufrufen und mit diesem keine Auswertung einer Funktion argument(en) durchgeführt.
Bearbeitet werden, um Fehler zu korrigieren notiert @cmasters Kommentar.
In
... die
return
ed Ausdruck nicht zeigen short-circuit-evaluation, aber der Funktionsaufruf nicht.Versuchen Sie anrufen
Dem Aufruf der Funktion wertet
1 /0
, obwohl es nie benutzt, daher verursacht - wahrscheinlich - einer Division durch null Fehler.Relevanten Auszüge aus dem (Entwurf) ANSI-C-Standard sind:
und
Meine Vermutung ist, dass jedes argument ausgewertet wird, als ein Ausdruck, sondern, dass das argument der Liste als ganzes ist nicht ein Ausdruck, daher die nicht-SCE Verhalten ist obligatorisch.
Als eine eingelassene auf der Oberfläche von der Tiefe des C-standard, würde ich mich über eine ordnungsgemäß informiert Blick auf zwei Aspekte:
1 /0
produzieren Undefiniertes Verhalten?P. S.
Selbst bewegen Sie sich auf C++, und definieren
sc_and
alsinline
- Funktion, werden Sie nicht bekommen SCE. Wenn Sie definieren, wie ein C-makro, wie @alk tut Sie sicherlich.inline
Funktion ändert nicht die Semantik eines Funktionsaufrufs. Und die Semantik angeben, dass alle Argumente, die bewertet, als Sie richtig zitiert. Selbst wenn der compiler optimieren den Aufruf, sichtbares Verhalten, dürfen sich nicht ändern, ich. e.sc_and(f(), g())
muss sich Verhalten, als wenn beidef()
undg()
sind immer aufgerufen wird.sc_and(0, 1/0)
ist ein schlechtes Beispiel, weil es wird Undefiniertes Verhalten, und der compiler ist nicht erforderlich, selbst nennensc_and()
...inline
erhaltenen call-Semantik. Ich habe fest mit der Division durch null, wie es passt das Beispiel, und SCE glaube ich nicht oft genutzt, um vermeiden undefinierten Verhalten.Klar zu sehen, ternärer op kurzschließen versuchen Sie, den code leicht zu verwenden Funktionszeiger statt Integer:
Und kompilieren Sie es (sogar fast OHNE Optimierung:
-O0
!). Sehen Sieb()
wird nicht ausgeführt, wenna()
gibt false zurück.Hier die generierte assembly aussieht:
So wie die anderen richtig darauf hingewiesen, die Frage trick ist, machen Sie sich auf den ternären operator Verhalten, das so gar Kurzschluss (Aufruf, die "bedingte Bewertung") anstelle der parameter-evaluation on call (call-by-value), die NICHT zu einem Kurzschluss.
C ternären operator kann niemals kurzschließen, denn es wertet immer nur einen einzelnen Ausdruck eine (der Bedingung), um zu bestimmen, einen Wert, gegeben durch die Ausdrücke b und c, wenn ein Wert zurückgegeben werden können.
Folgenden code:
Es ist fast gleichbedeutend mit dem folgenden code:
Den Ausdruck eine gebildet werden kann, die durch andere Operatoren wie && oder || das kann Kurzschluss, weil Sie beurteilen können zwei Ausdrücke, die vor der Rückgabe einen Wert, aber das würde nicht berücksichtigt werden, da der ternäre operator tun, Kurzschluss-aber der Betreiber verwendet in dem Zustand, wie es in einem normalen if-Anweisung.
Update:
Dort ist etwas Debatte über der tenäre operator wird ein short-circuit operator. Das argument sagt, jeder Betreiber, der nicht bewerten, wie es Operanden hat Kurzschluss nach @aruisdante in den Kommentar unten. Wenn angesichts dieser definition, dann ist der ternäre operator wäre kurzschließen und in dem Fall ist dies die ursprüngliche definition bin ich einverstanden. Das problem ist, dass der Begriff "short-circuit" wurde ursprünglich verwendet, für eine bestimmte Art von operator erlaubt, dass dieses Verhalten und diese sind der Logik/Boolesche Operatoren, und der Grund, warum sind nur jene, die ist, was ich werde versuchen zu erklären.
Folgenden Artikel Short-circuit-Evaluation, die short-circuit-Auswertung ist nur genannten booleschen Operatoren umgesetzt in die Sprache in einer Weise, wo zu wissen, dass der erste operand wird dem zweiten irrelevant, das ist, für die && Betreiber wird der erste operand false, und für den operator || wird der erste operand wahr, die spec-C11 auch Hinweise in 6.5.13 Logischen UND-operator und 6.5.14 Logischen ODER-operator.
Dies bedeutet, dass für die Kurzschluss-Verhalten identifiziert werden, erwarten Sie zu identifizieren, es in einen operator bewerten müssen alle Operanden, die genau wie die booleschen Operatoren, wenn der erste operand nicht machen irrelevant die zweite. Dies steht im Einklang mit dem, was geschrieben wird in einer anderen definition für den Kurzschluss in MathWorks unter der "Logischen Kurzschluss" Abschnitt, da Kurzschluss kommt von den logischen Operatoren.
Als ich versucht habe, zu erklären, die C ternär, auch als ternäre wenn, wird nur ausgewertet, zwei Operanden aus, wertet Sie der erste, und wertet dann eine zweite, die entweder eine der beiden übrigen je nach dem Wert der ersten. Es macht immer das, sein nicht soll die Bewertung aller drei in jeder situation, so dass es keine "short-circuit" in jedem Fall.
Wie immer, wenn Sie sehen, dass etwas nicht stimmt, schreibt bitte einen Kommentar mit einem argument gegen diese und nicht nur ein downvote, das macht einfach die Erfahrung noch schlimmer, und ich glaube, wir können eine viel bessere Gemeinschaft, eine, die nur downvotes Antworten, die man nicht Zustimmen.
x = a ? b : 0;
ist semantisch das gleiche wie(a && (x = b)) || (x = 0);