return uart_rx() | (uart_rx() << 8);

#4870379
Lesenswert?

Bernd K. schrieb:
> Darf der Compiler die Reihenfolge der Funktionsaufrufe vertauschen?
>
>
1
> uint16_t uart_rx16(void) {
2
>   return uart_rx() | (uart_rx() << 8);
3
> }
4
>

Gegenfrage:
Ist ein zweimaliger Aufruf von uart_rx() wirklich das, was man an dieser 
Stelle haben will? Oder war es eher so gemeint:

1
uint16_t uart_rx16(void) {
2
  uint16_t temp = uart_rx();
3
  return temp | (temp << 8);
4
}
#4870895
Lesenswert?

Johann L. schrieb:
> Nein, eine Multiplikation mit 257 war nicht gemeint.
>
> Der TO will einen 16-Bit Wert aus zwei 8-Bit Werten zusammenbastelt, die
> über den UART empfangen wurden.  Und da macht es eben einen Unterschied,
> wo LSB und MSB im 16-Bit Ergebnis landen.

Ach so. Also sowas hier dann:

1
uint16_t uart_rx16(void)
2
{
3
    uint8_t lo_byte = uart_rx();
4
    uint8_t hi_byte = uart_rx();
5
    return (hi_byte << 8) | lo_byte;
6
}

Und schon stellt sich die ursprüngliche Frage gar nicht mehr, weil man 
saubere Sequence Points hat.

Für mich ein typischer Fall von "Quetsch nicht so viel Code in eine 
Zeile, dann lösen sich viele Probleme von ganz alleine".
Moderator #4874948
Lesenswert?

Mark B. schrieb:
> "Wenn ich möglichst wenig Code schreibe, dann ist das optimal. Also
> quetsche ich möglichst viele Anweisungen in eine Zeile, anstatt das
> Ganze auszuschreiben."

Der Ausdruck enthält gerade einmal zwei Operationen (| und <<). Das ist
IMHO nicht gequetscht, sondern die ganz natürliche Schreibweise für so
etwas. Etwa vergleichbar wäre

1
  return gain * x + offset;

Das würde auch niemand (außer den BASCOM-Programmierern ;-)) in mehrere
Zeilen aufdröseln:

1
  int gainedValue = gain * x;   // unnötig
2
  return gainedValue + offset;  // kompliziert

Der einzige Grund, warum man die Codezeile

1
  return uart_rx() | (uart_rx() << 8);

in zwei Anweisungen aufsplitten muss, ist der mehrfache Aufruf der
nebeneffektbehafteten Funktion uart_rx, deren Aufrufreihenfolge sonst
nicht definiert ist.
#4874954
Lesenswert?

Yalu X. schrieb:
> Der einzige Grund, warum man die Codezeile
>
>
>
1
>   return uart_rx() | (uart_rx() << 8);
2
>
>
> in zwei Anweisungen aufsplitten muss, ist der mehrfache Aufruf der
> nebeneffektbehafteten Funktion uart_rx, deren Aufrufreihenfolge sonst
> nicht definiert ist.

Und der Grund warum dies nicht getan wurde ist, dass der Programmierer 
meint dies in eine Zeile quetschen zu müssen.

q.e.d.
Moderator #4875168
Lesenswert?

Mark B. schrieb:
> Und der Grund warum dies nicht getan wurde ist, dass der Programmierer
> meint dies in eine Zeile quetschen zu müssen.

Ich glaube nicht, dass er unter irgendwelchen Zwängen steht.

Deswegen hat er ja nachgefragt, ob man das so machen kann, und nach den
ersten beiden Antworten auch sofort eingesehen, dass es so nicht geht.

Kritisieren solltest du also nicht ihn, sondern diejenigen, die solche
Konstrukte in ihren Code einbauen, ohne sich vorher zu vergewissern,
dass sie korrekt sind.
#4875315
Lesenswert?

@ Yalu X. (yalu) (Moderator)

>Deswegen hat er ja nachgefragt, ob man das so machen kann, und nach den
>ersten beiden Antworten auch sofort eingesehen, dass es so nicht geht.

Ein guter Compiler sollte da mindestens eine Warung ausspucken. Gute 
Programmiersprachen lassen solche Konstrukte gar nicht erst zu ;-)
Moderator #4875426
Lesenswert?

Falk B. schrieb:
> Ein guter Compiler sollte da mindestens eine Warung ausspucken.

GCC und Clang tun das jedenfalls nicht, vemutlich deswegen, weil der
Compiler i.Allg. gar nicht erkennen kann, ob eine Funktion Nebeneffekte
hat (bspw. dann, wenn er nur die Funktionssignatur, aber nicht deren
Implementation sieht).

Jörg W. schrieb:
> Wem das zu kompliziert ist, der sollte Bascom benutzen. ;-)

Daran hat ganz sicher auch Falk gedacht, als er schrieb:

Falk B. schrieb:
> Gute Programmiersprachen lassen solche Konstrukte gar nicht erst zu
> ;-)

So arg viel mehr Programmiersprachen, die keine zwei Funktionsaufrufe in
einem Ausdruck zulassen, gibt es nämlich gar nicht¹.

Auch von mir gibt's noch einen Augenzwinker-Smiley dazu: ;-)

———————————
¹) Es gibt aber immerhin welche (z.B. Java), bei denen im Gegensatz zu C
   die Auswertereihenfolge vollständig spezifiziert ist. Da wäre dann
   auch der Ausdruck des TE korrekt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren