Forum: Compiler & IDEs zuweisung mit Vergleichsoperator


von Uli (Gast)


Lesenswert?

Hallo in die Runde,

Frage zu diesem Code-Segment:
1
bool can_message_available(void)
2
{
3
  uint8_t n;
4
5
  cli();
6
  n = canix_rxq_size() > 0;
7
  sei();
8
9
  return n;
10
}

Die Zeile mit der Zuweisung an n verstehe ich nicht. Die Funktion 
canix_rxq_size() ist so definiert, dass sie ein uint8_t zurück gibt. 
Also wir dieser Rückgabewert an n zugewiesen. Aber welche Auswirkung hat 
"> 0" in dieser Zeile?

Viele Grüße, Uli

: Verschoben durch Moderator
von Stephan (Gast)


Lesenswert?

In n steht das Ergebnis des bool’schen Vergleichs von canix_rxq_size() > 
0

von Einer (Gast)


Lesenswert?

Erst wird der Ausdruck auf der rechten Seite ausgewertet,
und dann das Ergebnis zugewiesen.
Ich schreibe da auch gern mal:
1
 n = (canix_rxq_size() > 0);

von A. B. (Gast)


Lesenswert?

Uli schrieb:
> bool can_message_available(void)
> {
>   uint8_t n;
>
>   cli();
>   n = canix_rxq_size() > 0;
>   sei();
>
>   return n;
> }

Wer so etwas schreibt, ist doppelt blöd: erstens ist 'n' für diesen 
Zweck ziemlich ungeschickt, da denkt man automatisch an eine Zahl. 
Zweitens, und das ist eine unmittelbare Konsequenz, kommt man dadurch 
bei der Zuweisung ins Schleudern, man fragt sich sofort, ob '(n = 
canix_rxq_size()) > 0;' oder 'n = (canix_rxq_size() > 0);' gemeint ist. 
Wesentlich geschickter wäre:

bool can_message_available(void)
{
  uint8_t is_available;

  cli();
  is_available = (canix_rxq_size() > 0);
  sei();

  return is_available;
}

Das mehr an Tipparbeit rentiert sich auf lange Sicht, denn wenn man ein 
paar Wochen später noch mal dahin schaut, muss man bei der urspr. 
Variante selbst erst man überlegen, was für einen Murks man da 
angerichtet hat.

von A. S. (Gast)


Lesenswert?

es sei noch angemerkt, dass der Typ bool ja existiert und durchaus für n 
oder is_available verwendet werden kann.

Selbst wenn das nicht so performant sein mag, weil bool 16 oder 32 Bit 
ist. Wenn man es nicht gemessen hat, ist es zweifelhaft, dass es 
langsamer ist. Und wenn man es gemessen hat, sollte man das im Kommentar 
berücksichtigen (Achtung: uint8_t weil es 4 Takte länger sind in der 
Version 1.0 des Kompilers und die Routine pro Sekunde 11 mal aufgarufen 
wird!)

von Uli (Gast)


Lesenswert?

Danke für eure Info. Es ist mir jetzt klar, allerdings war die 
Schreibweise für mich eher unübersichtlich.

Uli

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Uli schrieb:
> Es ist mir jetzt klar, allerdings war die Schreibweise für mich eher
> unübersichtlich.

Diese Schreibweise hätte den gleichen Effekt:
1
    if (canix_rxq_size() > 0)
2
    {
3
        n = 1;
4
    }
5
    else
6
    {
7
        n = 0;
8
    }

Wenn Du das lesbarer findest (ich persönlich sehe das so), dann benutze 
das. Der resultierende Assembler-Code dürfte derselbe sein.

P.S.
Ähnlich sähe es aus, wenn man n wirklich als Bool definiert, welches ja 
auch der Typ des Rückgabewertes der Funktion ist. Hier könnte man dann 0 
und 1 durch die entsprechenden Wahrheitswerte austauschen.

: Bearbeitet durch Moderator
von Peter D. (peda)


Lesenswert?

Unter C hat jeder Ausdruck einen Wert.
Man kann ihn daher einer Variablen zuweisen oder mit if, while, for 
direkt testen ob der Wert nicht 0 ist.
Implizit lautet ein if ausgeschrieben:
1
  if ( (bool)(canix_rxq_size() > 0) != false )

von Dussel (Gast)


Lesenswert?

A. B. schrieb:
> Zweitens, und das ist eine unmittelbare Konsequenz, kommt man dadurch
> bei der Zuweisung ins Schleudern, man fragt sich sofort, ob '(n =
> canix_rxq_size()) > 0;' oder 'n = (canix_rxq_size() > 0);' gemeint ist.
Was sollte denn
(n = canix_rxq_size()) > 0;
bewirken? Dann hätte man einen Vergleich, dessen Ergebnis nicht 
ausgewertet wird. Damit wäre der Vergleich unsinnig.

Persönlich mag ich diese Schreibweise, weil sie so schön 
Nerd/Hacker-mäßig aussieht, aber in der praktischen Anwendung würde ich 
die nicht empfehlen.

von Teo D. (teoderix)


Lesenswert?

n = canix_rxq_size() ?  1:0;
(Könnt aber die längste Variante sein!?)

Was spricht eigentlich gegen
n = (bool) canix_rxq_size(); ?

von A. S. (Gast)


Lesenswert?

Teo D. schrieb:
> Was spricht eigentlich gegen
> n = (bool) canix_rxq_size();

Es muss nicht sein, dass bool binär ist. Es kann auch ein int oder uint8 
oder sonstwas in einer C-Version ohne bool sein und liefert dann nicht 0 
oder 1 zurück.

Alternativ (wenn ggf negativ auch true ist)
n=!!canix_rxq_size();

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Uli schrieb:
> Es ist mir jetzt klar, allerdings war die
> Schreibweise für mich eher unübersichtlich.

Rechts vom "=" steht ein Ausdruck, und dessen Wert wird n zugewiesen.

Ob das unübersichtlich ist, ist eine Frage der Gewohnheit.  Ich 
persönlich bevorzuge die platzsparende Alternative gegenüber dem 
länglichen if-else.

Sinnvoller als der Einsatz wie im Beispiel ist bei komplexeren Abfragen 
wie
1
    uint8_t n = (a > 1) + (b > 2) + (c > 3);
2
    switch (n)
3
    {
4
        case 2:
5
            // Mindestens 2 Bedingungen sind erfüllt.
6
            ...
7
    }
In dem Fall sind Klammern um die Bedingungen erforderlich.

Bei einer einzigen Bedingung Klammern für bessere Übersichtlichkeit zu 
setzen kann man machen; aber wie oben mangelnde Sprachkenntnis als 
Begründung für Klammersetzung anzuführen ist einer der schlechtesten 
Argumente überhaupt.

Und ob man bei meinem Beispiel über eine Zwischenvariable geht oder
1
switch ((a > 1) + (b > 2) + (c > 3))
verwendet, ist natürlich dem Coding Style überlassen.

Wenn die Bedingungen komplexer sind, kann man auch auf mehrere Zeilen 
aufteilen:
1
    uint8_t n_conditions = 0;
2
    n += bedingung_1 (wert1 + wert2 * wert3);
3
    n += bedingung_2 (wert3 + wert4 - wert5);
4
    n += bedingung_3 (wert1 * wert2 * wert4);
5
    switch (n) ...

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.