Warum die Ausgabe des unten genannten Programms ist 0
nicht 20
?
#include <stdio.h>
int main()
{
int i = 10, j = 0;
if (i || (j = i + 10))
/* do something */;
printf("%d\n",j);
}
duslabo
Warum die Ausgabe des unten genannten Programms ist 0
nicht 20
?
#include <stdio.h>
int main()
{
int i = 10, j = 0;
if (i || (j = i + 10))
/* do something */;
printf("%d\n",j);
}
Grijesh Chauhan
Ja, das Konzept heißt Kurzschluss (im logischen &&
, ||
Operatorausdruck).
Im Falle eines logischen Ausdrucks (inkl ||
, &&
) Compiler stoppt den Auswertungsausdruck, sobald das Ergebnis ausgewertet wird (und speichert Ausführungen).
Die Technik für Kurzschluss ist:
!0 || any_expression
== 1
Also any_expression
nicht auswerten müssen.
Und weil in Ihrem Ausdruck i
ist nicht null, sondern 10, also können Sie denken, wenn Bedingung (i || (j = i + 10))
genauso wie i
.
Logischer ODER-Operator:
Das
||
Operator garantiert Links-nach-Rechts-Auswertung; es gibt einen Sequenzpunkt nach der Auswertung des ersten Operanden. Wenn der erste Operand vergleichtunequal
zu0
der zweite Operand istnot
ausgewertet.
Ähnlich für && (and-Operator):
0 && any_expression
== 0
Also any_expression
nicht auswerten müssen.
In deinem Ausdruck:
(i || (j = i + 10) )
------------
^
| Could evaluate if i is 0,
as i = 10 (!0 = true), so j remains unchanged as second operand is not evaluated
Für oder ||
Die Antwort des Bedieners kann entweder 0 oder 1 sein. Um die Ausführung zu speichern, stoppt die Auswertung, sobald Ergebnisse gefunden werden. Wenn also der erste Operand ungleich Null ist, wird das Ergebnis sein 1
(wie oben) für den Ausdruck. Also für den ersten Operanden i = 10
vergleicht ungleich 0, dem zweiten Operanden (j = i + 10)
wird nicht so bewertet j
Überreste 0
daher ist die Ausgabe Ihres Codes 0
.
Hinweis: Das Kurzschlussverhalten ist nicht nur in C vorhanden, sondern das Konzept ist vielen Sprachen wie Java, C++ und Python gemeinsam. (aber nicht alle zB VB6).
In C war das Kurzschließen von logischen Ausdrücken garantiert schon immer ein Merkmal von C. Es war wahr, als Dennis Ritchie die erste Version von C entwarf und implementierte, immer noch wahr im C-Standard von 1989 und bleibt wahr im C99-Standard.
Ein verwandter Beitrag: Ist das Kurzschließen boolescher Operatoren in C/C++ vorgeschrieben? Und Auswertungsreihenfolge?
Ehrlich gesagt, viel zu lange Antwort.
– Antonio
19. Juli 2013 um 8:28 Uhr
“Im Falle eines logischen Ausdrucks stoppen die meisten Compiler den Auswertungsausdruck, sobald das Ergebnis ausgewertet wird (um Ausführungen zu sparen).” – Nein, es ist nicht vorbei “die meisten Compiler”sondern durch alle die sich C-Compiler nennen, weil es der Standard vorschreibt. Meistens geht es also nicht nur um die Leistung, sondern um die Korrektheit, z. B. denken Sie darüber nach while(node && node->value)
was furchtbar falsch wäre, wenn der Standard dies nicht tun würde Garantie kurzschließen.
– Christian Rau
19. Juli 2013 um 9:42 Uhr
@GrijeshChauhan Sie könnten damit nicht einverstanden sein (nur das Standardkomitee kann das beantworten und Sie könnten sehr wohl Recht haben mit dem ursprünglichen Zweck). Dem können Sie jedoch auf keinen Fall widersprechen “die meisten Compiler” tun dies, aber alle. Ein Compiler, der dies nicht tut, ist kein C-Compiler und es wäre wie so etwas wie =
oder +
nicht wie erwartet funktionieren würde, können Sie sich nicht darauf verlassen, dass irgendein Code mit einem solchen Compiler funktioniert. So wie es aussieht, klingt Ihre Antwort so, als wäre dies nur eine Optimierung der Compiler-Implementierung nicht der Fall.
– Christian Rau
19. Juli 2013 um 9:51 Uhr
@Grijesh: Sie müssen diesen Satz nur präzisieren, damit die Leute beim Lesen Ihrer Antwort keine falsche Vorstellung bekommen. Sie sehen, dass bereits zwei Personen Ihre Antwort missverstanden haben. Eines der großartigen Dinge an SO ist, dass Antworten immer möglich sind verbessert.
– PaulR
19. Juli 2013 um 10:14 Uhr
Danke, es ist nicht mehr irreführend, +2.
– Christian Rau
19. Juli 2013 um 11:22 Uhr
||
ist ein Kurzschluss -Operator – Wenn die linke Seite als wahr ausgewertet wird, muss die rechte Seite nicht ausgewertet werden. Also, in Ihrem Fall seit i
ist dann der Ausdruck wahr j = i + 10
wird nicht ausgewertet. Wenn Sie einstellen i
auf 0 aber dann die rechte Seite Wille bewerted werden,
Ist diese Funktion vom Compiler abhängig?
– nj-ath
19. Juli 2013 um 16:20 Uhr
@TheJoker Nein, in C ist das Kurzschließen logischer Ausdrücke garantiert schon immer ein Merkmal von C.
– Grijesh Chauhan
19. Juli 2013 um 16:25 Uhr
Im if (i || (j = i + 10))
, müssen zwei boolesche Ausdrücke ausgewertet werden. Die Sache ist, dass die erste wahr ist, daher besteht keine Notwendigkeit, die zweite zu berechnen. Es wird einfach ignoriert.
tczf
Weil ||
ist ein Kurzschlussoperator (so ist die &&
Operator).
also rein (i || j = i+10)
, i
ist 10, linker Teil von ||
stimmt, der Ausdruck j = i+10
ist nicht passiert, infolgedessen j=0
.
Kurzgeschlossener boolescher Ausdruck.
– jxh
19. Juli 2013 um 8:01 Uhr
Dies mag wie eine dumme Frage erscheinen, aber ich lerne – wie könnte das Programm jemals 20 ausgeben? Hat es etwas speziell mit C zu tun?
– Andy
19. Juli 2013 um 16:36 Uhr
@Andy (1)–program könnte ausgeben
20
nur wenni = 0
(die Änderung zum Ausführen des Ausdrucks gebenj = i + 10
). (2) Nein, dieser Code ist in C++ gültig, sogar in Java, weil wir beides tun können=
innerhalbif()
und beide unterstützen Kurzschluss. — Es wäre interessant zu wissen, dass sogar Python Kurzschluss unterstützt, aber diesen Ausdruckif (i || (j = i + 10))
ist in Python nicht gültig, weil=
inif
ist Syntaxfehler.– Grijesh Chauhan
19. Juli 2013 um 16:43 Uhr
@ Andy ja, und du weißt schon, na ? dass irgendjemand
non-0
Wert isttrue
in C und soi
(=10) istture
.– Grijesh Chauhan
19. Juli 2013 um 16:53 Uhr
@JeshwanthKumarNK Das habe ich in meiner Antwort hinzugefügt
||
und&&
Operatoren führt Sequenzpunkt so ein++i || ++i
ist kein undefiniertes Verhalten 🙂 wohingegen++i | ++i
ist undefiniert 🙁 . verstanden?– Grijesh Chauhan
25. Juli 2013 um 9:17 Uhr