Forum: Mikrocontroller und Digitale Elektronik Verkürzte Schreibweise if


von Michael D. (Gast)


Lesenswert?

Hallo zusammen,

ich bin gerade dabei mich in fremden Code einzuarbeiten und dabei auf 
folgendes gestossen:

int func(void)
{
  u16 ret;
  int status;

  status = func2(&ret);
  return status ? : ret;  // Diese Zeile verstehe ich nicht
}

Prinzipiell kenne ich ka die verkürzte if Schreibweise so:

x ? y : z
FALLS x DANN y SONST z

* Irgendwie fehlt mir hier der DANN Zweig
* Der SONST Zweig würde u16 zurückgeben und kein int

Hat irgendwer einen Rat?

Danke, Michael

von Fabian B. (fabs)


Lesenswert?

Die Zeile ist ausgeschrieben

Wenn status dann <nichts> sonst ret.

Der Returnwert ist also leer oder ret wenn nicht status.

int kann auch ein u16 sein, kommt auf die Plattform an.

Gruß
Fabian

von Michael D. (Gast)


Lesenswert?

Hallo Fabian,

Vielen Dank!

Lg, Michael

von Karl H. (kbuchegg)


Lesenswert?

Michael D. schrieb:

>   return status ? : ret;  // Diese Zeile verstehe ich nicht

> Prinzipiell kenne ich ka die verkürzte if Schreibweise so:
>
> x ? y : z

> Hat irgendwer einen Rat?

IMHO ist das ein Fehler.

Da wirst du wohl die Funktion analysieren müssen um festzustellen, was 
ein sinnvoller Returnwert im Falle von status ist.

Aber eine int Funktion kann nicht einfach <nichts> zurückgeben.

von (prx) A. K. (prx)


Lesenswert?

x ? : y ist eine GCC spezifische Abkürzung für x ? x : y

http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Conditionals.html#Conditionals

von Michael D. (Gast)


Lesenswert?

Hallo A. K.

Vielen Dank!!

Mfg,
Michael

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:
> x ? : y ist eine GCC spezifische Abkürzung für x ? x : y
>
> http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Conditionals.html#Conditionals

Schrecklich. Warum macht man sowas? Da sind meines Erachtens Fehler 
vorprogrammiert, wenn der Compiler etwas akzeptiert, was eigentlich eher 
ein Syntax-Error ist.

Jedenfalls sah es Karl Heinz bis eben noch genauso :-)

Okay, die Argumentation, man könne damit einen Side-Effect vermeiden, 
nämlich die Wiederholung von Ausdrücken in Makros und damit eine 
zweifache Evaluation des Ausdrucks, kann ich ja noch nachvollziehen. 
Aber dieses Problem zu erschlagen mit einer "Erweiterung" der Syntax des 
?-Operators halte ich für grenzwertig.

Gruß,

Frank

von (prx) A. K. (prx)


Lesenswert?

Frank M. schrieb:

> Schrecklich. Warum macht man sowas? Da sind meines Erachtens Fehler
> vorprogrammiert, wenn der Compiler etwas akzeptiert, was eigentlich eher
> ein Syntax-Error ist.

Ich sehe das weit weniger kritisch. "Vorprogrammierte Fehler" weil der 
Compiler Dinge akzeptiert, die nicht dem Standard entsprechen, klingt 
für mich etwas nach Panik.

Manche GCC Erweiterungen sind/waren Versuchsballons, die teilweise 
später in C99 eingeflossen sind.

Aber dann schreib halt -ansi -pedantic-errors rein und du bist es los.

von eProfi (Gast)


Lesenswert?

Schon oft habe ich gelesen, dass die ?-Anweisung eine Kurzschreibweise 
für if sein soll. Kann ich aber gar nicht bestätigen.

bei if wird eine Bedingung ausgewertet und bei zutreffen der 
"then"-Zweig ausgeführt, bei Nicht-Zutreffen - falls vorhanden - der 
Else-Zweig.

Im Gegensatz dazu nimmt der ?-Ausdruck einen Wert in Abhängigkeit der 
Bedingung an, damit sind Sachen wie

neu=bedingung?17:25
möglich.
Mit if würde das heißen:
if(bedingung)neu=17;else neu=25

Aber ich kann es auch in einen Funktionsaufruf legen:
funktion(kalt?wärmen:kühlen)
In if-Schreibweise
if(kalt)funktion(wärmen);else funktion(kühlen)

So gern ich die ?:-Syntax mag, die Implementierung im Compiler habe ich 
oft ineffektiv gesehen.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Aber eine int Funktion kann nicht einfach <nichts> zurückgeben.
In PHP geht das sehr wohl. Da kann man auch wild verschiedene Datentüpen 
innerhalb der Funktion zurückgeben unter anderem auch "nichts" wobei das 
einfach darin resultiert das man null/false/0 bekommt (je nach 
Auswertung). Er hat ja nicht geschrieben das es um C und GCC handelt ;P
JS kennt es auch, das funktionen nicht immer einen (expliziten) 
Returnwert haben.

von Klaus W. (mfgkw)


Lesenswert?

Die Funktion des TE sieht aber doch etwas nach C aus?

von (prx) A. K. (prx)


Lesenswert?

eProfi schrieb:

> So gern ich die ?:-Syntax mag, die Implementierung im Compiler habe ich
> oft ineffektiv gesehen.

Mit hochoptimierten Compilern und Profiling, wo wenig verwendete 
Codezweige weggeschoben werden, hat sich das geändert. Ganz besonders 
aber bei Architekturen mit bedingter Ausführung von Befehlen (z.B. ARM) 
war das von Anfang an recht effizient umsetzbar.

von (prx) A. K. (prx)


Lesenswert?

eProfi schrieb:

> Aber ich kann es auch in einen Funktionsaufruf legen:
> funktion(kalt?wärmen:kühlen)

Abgesehen von den Umlauten natürlich schon. Wenn gern etwas 
unkonventioneller sein darf, dann auch so:
  (kalt?waermen:kuehlen)(10);

Der historische Hintergrund von ?: ist aber weniger eine 
Kurzschreibweise von if/else. Vielmehr liessen sich nur so wichtige 
Funktionen wie getc(f) effizient als Makros implementieren - inlining 
per Präprozessor. Heute kann man das mit ganz offiziellen 
Inline-Funktionen sprachlich eleganter umsetzen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Schrecklich. Warum macht man sowas? Da sind meines Erachtens Fehler
> vorprogrammiert

Ich finde es zwar auch schrecklich in diesem Falle :), aber Fehler
sind hier keineswegs programmiert.  Die meisten C-Programmierer
meiden den ternären Operator wie der Teufel das Weihwasser, weil sie
ihn nie so gut verstanden haben, dass sie ihn "flüssig lesen" können.
Die paar, die ihn benutzen, sind sich daher in ihrer Sache relativ
sicher, und solange kein anderer Compiler auf die Idee kommt, den
weggelassenen ersten Teil als eine völlig andere Erweiterung zu
definieren, schmeißt er einfach nur einen Syntaxfehler, ist also
auch kein Portabilitätsproblem.

Wenn man die GCC-Erweiterungen nicht haben will, sollte man halt
immer mit »-std=c99 -Wall -Wextra -pedantic« compilieren.

Warum man sowas implementiert, ist auch klar: weil die Situation,
dass man ein fehlendes Ergebnis durch etwas anderes ersetzen will,
im praktischen Leben offenbar häufig man auftritt.  (Allerdings kannte
ich diese GCC-Erweiterung bis soeben auch noch nicht.)

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:

> im praktischen Leben offenbar häufig man auftritt.  (Allerdings kannte
> ich diese GCC-Erweiterung bis soeben auch noch nicht.)

Recht verbreitet ist diese Technik als || Operator in Perl, der ja kein 
logisches 0/1 erzeugt, sondern die Operanden durchreicht.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch schrieb:
> Warum man sowas implementiert, ist auch klar: weil die Situation,
> dass man ein fehlendes Ergebnis durch etwas anderes ersetzen will,
> im praktischen Leben offenbar häufig man auftritt.

Kann ich mir nicht so richtig vorstellen.
Die Bedingung darf dann kein Vergleich sein, sondern muß ein Wert sein.
Und nur der Wert 0 wird dann durch was anderes ersetzt.

Ist die Bedingung ein Vergleich, dann spart man gerade mal das Schreiben 
der "1" ein.

Die Rückgabe eines Vergleichs erzeugt oftmals mehr Code als ein Sprung 
bei !=0, da dann ja explizit nach 0/1 gewandelt werden muß.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

> Warum man sowas implementiert, ist auch klar: weil die Situation,
> dass man ein fehlendes Ergebnis durch etwas anderes ersetzen will,
> im praktischen Leben offenbar häufig man auftritt.  (Allerdings kannte
> ich diese GCC-Erweiterung bis soeben auch noch nicht.)

Ditto.

Ich werde das auch in weiterer Folge nicht verwenden. Mir genügt es in 
solchen Fällen eine Hilfsvariable zu Hilfe zu nehmen, die mir das 
Zwischenergebnis aufnimmt.

Und dort, wo der ternäre Operator tatsächlich unglaublich praktisch ist 
(in Argumentlisten von Funktionsaufrufen) hab ich selten komplizierte 
Ausdrücke, deren doppelte Evaluierung es zu vermeiden gilt.


Das es derartige Erweiterungen hauptsächlich nur im gcc gibt, hat einen 
anderen Grund:
Jemand überlegt sich eine Spracherweiterung, die er vernünftig und gut 
findet. Nun kann nicht einfach jeder kommen und die Sprache C erweitern. 
Da gibt es Normungsgremien, die solche Dinge beschliessen. Dort wird ein 
Antrag auf Änderung eingereicht (samt Begründung, Auswirkungen etc) und 
das Gremium beschliesst oder beschliesst nicht, dass diese Änderung in 
den offiziellen Sprachstandard eingebracht wird.
Nun ist es aber so, dass die Chancen einen derartigen Antrag 
durchzubringen enorm steigen, wenn man einen Compiler vorweisen kann, 
der diese Erweiterung bereits enthält. Man dokumentiert damit ,dass die 
Spracherweiterung prinzipiell machbar ist, mit den bisherigen C-Regeln 
nicht in Konflikt steht und kann anhand von realen Beispielprogrammen 
die Erweiterung auch in Aktion zeigen. Kurz und gut: Reicht man den 
Antrag ein, ist es extrem hilfreich einen gepatchten Compiler zur 
Verfügung zu haben. Und da bietet sich der gcc natürlich an.

von Peter D. (peda)


Lesenswert?

Es gibt aber auch durchaus sehr praktische GCC-Erweiterungen, z.B. die 
Bereichsangaben bei switch/case.

Ansonsten 65536 Cases hinschreiben zu müssen, macht den Code nicht 
gerade lesbarer.

Und diese unsäglichen else/if Monster auch nicht. Sie werden auch lange 
nicht so effektiv optimiert, wie switch/case mit Bereichen.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Es gibt aber auch durchaus sehr praktische GCC-Erweiterungen, z.B. die
> Bereichsangaben bei switch/case.

Ja, finde ich auch.  Wenn muss man denn nerven, damit wir das mal
im C1x wiederfinden werden? ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.