Hallo ,
ich bin beim Experimentieren mit Code für GLCDs auf solche Passagen
gestoßen und wundere mich über das Fragezeichen:
http://members.chello.at/~easyfilter/bresenham.html
xx += sx; xx *= sx = x0 < x2 ? 1 : -1; /* x step direction */
yy += sy; yy *= sy = y0 < y2 ? 1 : -1; /* y step
direction */
Was für eine Konstruktion ist das da mit dem Fragezeichen und dem
Doppelpunkt?
Wo könnte man darüber etwas nachlesen?
Wäre für Tipps dankbar.
mit freundlichem Gruß
am wichtigsten ist dies hier:
Unless you are writing time critical code (and lets face it, thats
unlikely) the more efficent code is not much of a reason to use this
construct. I feel that it has its uses, but should not be lost into some
complex statement, but, since when did C programmers worry if anyone
else could read their code ;-)
roehrevorheizer schrieb:> am wichtigsten ist dies hier:> Unless you are writing time critical code
Der Teil ist allerdings mit aktuellen Compilern Unsinn. Der
Fragezeichenoperator führt zu keinem schnelleren Code, als eine
if/else-Konstruktion.
Oliver
Das mit dem ternary operator ist m.E. nicht schwieriger zu lesen als ein
if-Konstrukt. Ist halt so wie mit vielen Dingen: "was der Bauer nicht
kennt, das frißt er nicht".
Es gibt eine Sache, die der ternary operator besser/mehr kann als
if/else:
Markus F. schrieb:> Das mit dem ternary operator ist m.E. nicht schwieriger zu lesen als ein> if-Konstrukt. Ist halt so wie mit vielen Dingen: "was der Bauer nicht> kennt, das frißt er nicht".
Genau das. In vielen Fällen ist es deutlich einfacher zu lesen. Vor
Allem, wenn auch noch sinnvoll kommentiert ist.
>> Normalerweise benutze ich diesen Operator aber nur für true/false.
Kurz, übersichtlich und für einen erfahrenen C- oder Java-Programmierer
problemlos zu lesen. So sollte man Operatoren meiner Meinung nach
nutzen.
Oliver S. schrieb:> Der Teil ist allerdings mit aktuellen Compilern Unsinn. Der> Fragezeichenoperator führt zu keinem schnelleren Code, als eine> if/else-Konstruktion.
Es gibt keinen Deckel, der auf alle Töpfe paßt.
Manchmal ist ?: schneller und manchmal if/else.
Peter Dannegger schrieb:> Manchmal ist ?: schneller und manchmal if/else.
Na ja, jeder einigermaßen anständige Compiler sollte für beide Varianten
gleich schnellen Code erzeugen. Semnatisch ist das schließlich absolut
identisch.
Oliver
Oliver S. schrieb:> Na ja, jeder einigermaßen anständige Compiler sollte für beide Varianten> gleich schnellen Code erzeugen. Semnatisch ist das schließlich absolut> identisch.
ja nach Anwendung aber nicht.
1
if(a<b)
2
foo(a)
3
else
4
foo(b);
vs
1
foo(a<b?a:b)
hier könnte ich mir durchaus vorstellen das nicht der gleiche asm code
generiert wird.
Peter II schrieb:> hier könnte ich mir durchaus vorstellen
Kannst du.
Peter II schrieb:> das nicht der gleiche asm code> generiert wird.
Warum? Wenn du es genau wissen willst, prüf es doch einfach nach, mit
eingeschalteter Optimierung.
Oliver
Oliver S. schrieb:> Warum?
weil es 2 verschiedene dinge sind, beim IF sind 2 funktionsaufrufe beim
? nur einer.
> Wenn du es genau wissen willst, prüf es doch einfach nach, mit> eingeschalteter Optimierung.
dafür habe ich hier kein passendes System am laufen.
Random ... schrieb:> Wieder mal mein Lieblingsbeispiel :-)led_out(1 << (ledCnt = ++ledCnt<8 ?> ledCnt : 0));>> Normalerweise benutze ich diesen Operator aber nur für true/false.
Das ist aber schon ein ziemliches Stückchen. Auch wenn ich nicht ganz
unerfahren bin, bevorzuge ich den langen Weg. Die Kurzschreibweise muß
ich ja schließlich auch im Kopf wieder "unfolden", um dahinter zu
steigen. Da ist eine ordentliche lange Schreibweise sehr viel
einleuchtender, insbesondere, wenn keine Kommentare im Quelltext
vorhanden sind. Hatte das schon und das macht keinen Spaß, wenn der
Urheber von kryptischem Code der Meinung ist, daß alles sich nach ihm zu
richten hat und "the code is the comment" oberste Prämisse ist. Das kann
sich im Projekt sehr verzögernd auswirken.
Mir kann auch keiner erzählen, daß er nach einem halben Jahr noch gena
weiß, was er an so einer üblen Stelle bewirken wollte, ohne mehrfach
über den Code zu gehen. Deshalb: Der lange Weg ist der bessere.
Peter II schrieb:> weil es 2 verschiedene dinge sind, beim IF sind 2 funktionsaufrufe beim> ? nur einer.
Das ist doch Quark. Der ASM macht einen Branch oder so je nach Prozessor
draus. Denkst du nicht, daß der Compiler beide Varianten in dieselbe
Form überführt, bevor er es übersetzt? Beides hat dieselbe Wirkung. Du
machst dir damit um den Preis der "Coolness" nur selber das Leben
schwer.
plex schrieb:> Das ist doch Quark. Der ASM macht einen Branch oder so je nach Prozessor> draus.
Nö, der Assemblercode kann manchmal gleich sein, ist es aber oft nicht.
Es gibt 2 Hauptunterschiede:
Der ? Operator ist ein Sequence point.
Der ? Operator hat einen Wert, if aber nicht.
SF schrieb:> D.H. mit den richtigen Optimierungseinstellungen verhält sich der> Compiler, so wie erwartet.
was ist an -Os richtiger als -Os - wird sind bei GCC nicht beim µC.
Außerdem ist es auch mit -Os auf einen PC nicht gleich. Und nicht so wie
du erwartest.
plex schrieb:> Mir kann auch keiner erzählen, daß er nach einem halben Jahr noch gena> weiß, was er an so einer üblen Stelle bewirken wollte, ohne mehrfach> über den Code zu gehen. Deshalb: Der lange Weg ist der bessere.
der Code sollte so geschrieben werden, dass Kollegen ihn lesen können.
Das bedeutet nicht, dass ihn jeder Berufsanfänger lesen können muss, der
sich nicht die Mühe macht, eine Sprache vor der Verwendung zu lernen.
?: ist ein Operator, mit dem sich z.B: auch Konstanten initialisieren
lassen:
Peter II schrieb:> was ist an -Os richtiger als -Os - wird sind bei GCC nicht beim µC.
Du warst bei -O2 und das ist nun mal was anderes als -Os.
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html> Außerdem ist es auch mit -Os auf einen PC nicht gleich. Und nicht so wie> du erwartest.
Und warum reitest du dann auf dem anders generierten ASM Code rum? Kann
dir doch egal sein was beim PC-ASM rauskommt, wenn Codesize keine Rolle
spielt und das Ergebnis stimmt.
plex schrieb:> Und warum reitest du dann auf dem anders generierten ASM Code rum? Kann> dir doch egal sein was beim PC-ASM rauskommt, wenn Codesize keine Rolle> spielt und das Ergebnis stimmt.
Ich wollte nur zeigen das mit am dem ? auch schnelleren code als mit if
schreiben kann. Oben hat jemand behauptet hat, in beiden Fälle kommt
der gleiche code raus - das stimmt nicht.
es bezog sich alles auf
Peter II schrieb:
> weil es 2 verschiedene dinge sind, beim IF sind 2 funktionsaufrufe beim> ? nur einer.
Das ist doch Quark. Der ASM macht einen Branch oder so je nach Prozessor
draus. Denkst du nicht, daß der Compiler beide Varianten in dieselbe
Form überführt, bevor er es übersetzt?
Peter II schrieb:> Das ist doch Quark. Der ASM macht einen Branch oder so je nach Prozessor> draus. Denkst du nicht, daß der Compiler beide Varianten in dieselbe> Form überführt, bevor er es übersetzt?
Wer lesen kann, ist strategisch im Vorteil:
Peter Dannegger schrieb:> Der ? Operator ist ein Sequence point.> Der ? Operator hat einen Wert, if aber nicht.
Peter Dannegger schrieb:> Der ? Operator ist ein Sequence point.
Genauso wie die "Controlling Expression" im if-statement. Kein
Unterschied.
> Der ? Operator hat einen Wert, if aber nicht.
Richtig. Genau deshalb gibt es den Operator. Drückt man das mit if/else
aus, braucht es dafür eine lokale Variable. Da es in Assembler aber
"einen Wert" nicht gibt, da muß alles irgendwo abgelegt werden, egal, ob
"Wert" oder "Variable", gibt es deshalb alleine keinen Grund,
unterschiedlichen Assemblercode zu erzeugen.
Oliver
Das stimmt aber so nicht ganz. Wenn du es richtig nach deiner
"contition" ausformulieren würdest, kämest du auf:
1
constintf;
2
if(a)
3
f=b;
4
else
5
f=a;
So wäre das richtig verwendet und steht deinem Ausdruck in nichts nach.
Ohne Voodoo und dazu noch übersichtlich.
Mit dem "!" (not) kann man gehörig auf die Nase fallen, wenn es sich
nicht um true/false Werte handelt. Alles schon gesehen.
plex schrieb:> const int f;> if (a)> f = b;> else> f = a;> So wäre das richtig verwendet und steht deinem Ausdruck in nichts nach.> Ohne Voodoo und dazu noch übersichtlich.
Nicht wirklich. Eher redudanter Code und dazu deutlich länger.
> Mit dem "!" (not) kann man gehörig auf die Nase fallen, wenn es sich> nicht um true/false Werte handelt. Alles schon gesehen.
Das wäre mir neu. Aber wer denkt true == 1, dem kann das schon
passieren.
Torsten schrieb:> das geht nichtplex schrieb:> const int f;> if (a)> f = b;> else> f = a;> ... und steht deinem Ausdruck in nichts nach.
Stimmt. Geht genauso wenig.
Oliver
avr schrieb:> Nicht wirklich. Eher redudanter Code und dazu deutlich länger.
Führt aber zu weniger Verwirrung und schnellerer Erfassung der Aufgabe
des Codes. Und jetzt komm hier nicht mit Redundanz und Sourcecodelänge
in Zeiten von Terabyte Festplatten um die Ecke. Da kann man Kommentare
auch gleich weglassen und sofort binär programmieren. Das ist nun gar
kein Argument.
plex schrieb:> avr schrieb:>> Nicht wirklich. Eher redudanter Code und dazu deutlich länger.> Führt aber zu weniger Verwirrung und schnellerer Erfassung der Aufgabe> des Codes.
1
if(haveError)
2
penColor=RED;
3
else
4
penColor=BLACK;
5
6
if(isOutputPin)
7
penStyle=NORMAL;
8
else
9
penStyle=ITALIC;
10
11
if(isAboveMaximum)
12
strcpy(fontName,"Times Roman");
13
else
14
strcpy(fontName,"Arial");
15
16
drawText(pinName,penColor,penStyle,fontName);
versus
1
drawText(pinName,
2
haveError?RED:BLACK,
3
isOutputPin?NORMAL:ITALIC,
4
isAboveMaximum?"Times Roman":"Arial"
5
);
die Variante ohne Hilfsvariablen mit ineinander geschaltelten if-else
Konstrukten, die in 6 unterschiedlichen Aufrufen von DrawText münden,
will ich mir erst gar nicht ausmalen.
Wie immer gilt: man kann jedes Sprachkonstrukt zum Vorteil des
Programmierers ausnutzen. Man kann es aber auch übertreiben und dann
dreht sich der Effekt ins Gegenteil um.
Karl Heinz schrieb:> Wie immer gilt: man kann jedes Sprachkonstrukt zum Vorteil des> Programmierers ausnutzen. Man kann es aber auch übertreiben und dann> dreht sich der Effekt ins Gegenteil um.
Hier muß ich dir beipflichten. Eine Sache noch: Wie sieht es beim Debug
aus? Meiner Erfahrung nach sind die Kurzkonstrukte da wirklich nicht
hilfreich, weil einfach die Übersicht fehlt (und auch die
Hilfsvariablen), wenn der Marker nur in derselben Zeile herumtanzt. Da
sind mir - wenn auch verschachtelte - if-Konstrukte sehr viel lieber.
Kann ja sein, daß nur ich und wenige Andere schlechte Erfahrungen mit
der Kurzschreibweise gemacht habe.
plex schrieb:> Wie sieht es beim Debug aus? ... (und auch die Hilfsvariablen)
Hilfsvariablen optimiert der Compiler sowieso gnadenlos weg, auf die
brauchst du also beim Debuggen nicht zu zählen.
Wenn du dir Zwischenwerte fürs Debuggen merken willst, dann musst
du entweder den Code verfolgen (in welchem CPU-Register steht was?),
oder du legst dir eine temporäre Variable an, die du “volatile”
markierst, und lässt den Compiler dahin den Wert schreiben.
Gleiches trifft auf die verschachtelten if-Konstrukte zu: wie wir
oben schon gesehen haben, ist die Chance groß, dass sie ohnehin den
gleichen Code produzieren wie die ?:-Operatoren, damit ist auch
klar, dass sich beim Debuggen keins vom anderen unterscheiden wird.
Je neuer der Compiler und je besser die CPU, um so größer die Chance,
dass man nichts mehr „geradlinig“ debuggen kann. „Bessere“ CPUs sind
hier Dinge wie ARM oder AVR im Vergleich zum alten i386, denn sie
haben deutlich mehr freie Register, die der Compiler nutzen kann.
Damit steigt aber die Chance, dass er eben auch im Codefluss deutlich
vom niedergeschriebenen C-Code abweichen kann.
Jörg Wunsch schrieb:> „Bessere“ CPUs sind> hier Dinge wie ARM oder AVR im Vergleich zum alten i386, denn sie> haben deutlich mehr freie Register, die der Compiler nutzen kann.
Du vergleichst da zwei unterschiedliche Rechnerarchitekturen: CISC
(i386) und RISC (ARM, AVR).
Das hat aber nichts mit "Besserer" CPU zu tun.
Detlef Kunz schrieb:> Das hat aber nichts mit "Besserer" CPU zu tun.
Aber mit dem, was der Compiler im Codeablauf für Freiheiten genießt.
Daher habe ich das „besser“ auch in Anführungszeichen geschrieben.
Außerdem ist ein AVR nicht so ganz ernsthaft RISC (im Sinne der
ursprünglichen RISC-Definition), und auch ein amd64 hat deutlich
mehr freie Register für den Compiler als ein i386, obwohl er wohl
nun ganz eindeutig CISC ist.
Jörg Wunsch schrieb:> und auch ein amd64 hat deutlich> mehr freie Register für den Compiler als ein i386, obwohl er wohl> nun ganz eindeutig CISC ist.
sicher?
so eindeutig ist das ganze schon lange nicht mehr.
Google: "i7 CISC oder risc"
Hallo plex,
plex schrieb:> Führt aber zu weniger Verwirrung und schnellerer Erfassung der Aufgabe> des Codes.
das ist wirklich eine Übungssache. Anfänger können sich oft auch nicht
die Operator precedence merken und machen dann vorsichtshalber mal um
alles eine Klammer. Natürlich auch der Lesbarkeit wegen. Ein erfahrener
Entwickler fragt sich, warum da Klammern sind, nimmt die Klammern in
Gedanken weg und ist erstaunt darüber, dass die Klammer überflüssig
waren und damit keine Aussage getroffen haben. Kleine Anekdote: Ein
Kollege von mir hat immer Klammer um den Rückgabewert einer Funktion
gemacht. Als er meinte, dass es so übersichtlicher wäre, habe ich Ihm
gesagt, er solle zwei Klammern drum machen, damit es noch
übersichtlicher wird ;-)
Also immer:
1
return((result));
> Da kann man Kommentare> auch gleich weglassen und sofort binär programmieren.
Das gleiche gilt für Kommentare. Wenn der Programmfluss mit Kommentaren
erklärt werden muss, es also kein Mittel gibt, diesen auch ohne
Kommentar klar erkennbar zu machen, dann ist das was "kompliziert".
Redundante Kommentare neigen dazu, sehr schnell zu altern, mit dem
Effekt, dass man dann Kommentare hat, die nicht mehr zu Code passen und
man sich fragt, was von beiden nun richtig ist.
Den schlimmsten Kode, den ich bis jetzt gesehen habe, hat sich vor
allem, durch viele Kommentare ausgezeichnet :-(
mfg Torsten
Torsten schrieb:> Kleine Anekdote: Ein> Kollege von mir hat immer Klammer um den Rückgabewert einer Funktion> gemacht.
Konsequenterweise müsste er dann auch schreiben
1
i=(5);
das ist dann genau aus dem gleichen Grund übersichtlicher :-)
>> das ist dann genau aus dem gleichen Grund übersichtlicher :-)
Finde ich gut, da weiss man auf jeden Fall in welcher Reihenfolge die 5
ausgewertet wird! ;-)
Hallo Leute,
na, mit so einer Frage zu einem seltenen Operator kann man aber eine
ganz schöne Lawine los treten!
Deshalb hier im Foto noch ein Beispiel für einen Operator oder einen
anderen. Aus Zeiten vor C.
Danke für die Zuschriften auch der Moderatoren und die Erweiterung
meines Wissens.
mfG
Also ich habe auch noch bisher keinen Fall erlebt wo ? oder if sich im
Assembler unterschieden hätte (mit Optimierung an).
Sehe auch nicht den Grund warum das der Fall sein sollte, ich würde auch
als Compiler ? und if gleichsetzen.
Ich persönlich nutze den ? Operator aber selber auch gerne, wenn auch
eigentlich nur für bedingte Zuweisungen alla:
a = d < f ? d : f;
PS hab mal mein Beispiel angegangen (kompiliert mit gcc -O2 -S).