www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Dereferenzierung und Postinkrement von Zeiger in einer Zeile


Autor: noips (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Zu dem Code unten habe ich folgende Frage:

Was passiert in der Zeile *PtrSPI_RecBuff++ = UCB1RXBUF ?

Wird hier UCB1RXBUF der Variable zugewiesen, auf die PtrSPI_RecBuff 
zeigt und der Zeiger anschließend inkrementiert. Oder passiert da was 
anderes?
uint8_t *PtrSPI_RecBuff;
PtrSPI_RecBuff = (uint8_t*) &SPI_RecBuff;

for (i=0; i < sizeof SPI_RecBuff; i++) {
    while (!(UCB1IFG&UCTXIFG));   // USCI_B1 TX buffer ready?
    UCB1TXBUF = 'a';              // turn on master for clock signal
    while(UCB1STAT&UCBUSY);       // wait until char is received
    *PtrSPI_RecBuff++ = UCB1RXBUF;
  }

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noips schrieb:
> Wird hier UCB1RXBUF der Variable zugewiesen, auf die PtrSPI_RecBuff
> zeigt und der Zeiger anschließend inkrementiert.

ja

Autor: noips (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Operatoren "*" (Dererenzierung) und ++ haben eigentlich die gleiche 
Priorität laut 
http://de.wikibooks.org/wiki/C-Programmierung:_Lis.... 
Ist das dann nicht so, dass sie von links nach rechts abgearbeitet 
werden, also

*ptr++   entspricht   ((*ptr)++)  ?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wäre nur der Fall, wenn * stärker als das ++ binden würde.  Dann 
wäre das Objekt von ++ nicht p, sondern *p.  So hast Du *p, dann p++.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm eine andere Tabelle, z.B. diese hier:

  http://www.difranco.net/cop2220/op-prec.htm

Da hat der Postfixinkrementoperator Vorrang vor dem Verweisoperator.
*ptr++ ist also das Gleiche wie *(p++).

Autor: Daniel V. (danvet)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noips schrieb:
> Hallo zusammen!
>
> Zu dem Code unten habe ich folgende Frage:
>
> Was passiert in der Zeile *PtrSPI_RecBuff++ = UCB1RXBUF ?
>
> Wird hier UCB1RXBUF der Variable zugewiesen, auf die PtrSPI_RecBuff
> zeigt und der Zeiger anschließend inkrementiert. Oder passiert da was
> anderes?
>
>
> uint8_t *PtrSPI_RecBuff;
> PtrSPI_RecBuff = (uint8_t*) &SPI_RecBuff;
> 
> for (i=0; i < sizeof SPI_RecBuff; i++) {
>     while (!(UCB1IFG&UCTXIFG));   // USCI_B1 TX buffer ready?
>     UCB1TXBUF = 'a';              // turn on master for clock signal
>     while(UCB1STAT&UCBUSY);       // wait until char is received
>     *PtrSPI_RecBuff++ = UCB1RXBUF;
>   }
> 

Wäre wohl besser die beiden Operationen auseinander zu ziehen. Zum einen 
liest sich das besser. Zum anderen weiß man dann auch, was gemacht wird. 
Also:

*PtrSPI_RecBuff = UCB1RXBUF;
PtrSPI_RecBuff++;

Wer weiß, was der Compiler interpretiert..??

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel V. schrieb:
> Wer weiß, was der Compiler interpretiert..??
Ein Compiler interpretiert nicht, der geht nach einem festen Regelwerk 
vor.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel V. schrieb:

> Wäre wohl besser die beiden Operationen auseinander zu ziehen. Zum einen
> liest sich das besser.

Ist Ansichtssache

> Zum anderen weiß man dann auch, was gemacht wird.

Ist Übungssache, bzw. kennen der entsprechenden Bestimmungen.

> *PtrSPI_RecBuff = UCB1RXBUF;
> PtrSPI_RecBuff++;
>
> Wer weiß, was der Compiler interpretiert..??

Der Compiler 'interpretiert' das hinein, was ihm die genormten 
Sprachregeln vorschreiben. Kennt man die Regeln, dann weiß man auch, wie 
so etwas zu lesen ist. Ganz einfach :-)

Nicht falsch verstehen. Ich bin ein großer Verfechter der einfachen 
Schreibweise. Aber gerade C hat ein paar nette Dinge, die einem den Code 
bei minimal schlechterer Detail-Lesbarkeit kürzer und übersichtlicher 
machen.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Nimm eine andere Tabelle, z.B. diese hier:
>
>   http://www.difranco.net/cop2220/op-prec.htm
>
> Da hat der Postfixinkrementoperator Vorrang vor dem Verweisoperator.
> *ptr++ ist also das Gleiche wie *(p++).

Das ist jetzt leider falsch.

Auch diese Tabelle ist so zu lesen, daß alle Operatoren von ++
bis sizeof gleiche Priorität haben.
Sie stehen nur aus Platzgründen nicht nebeneinander, sondern
übereinander.

++ und * (als Dereferenzierung) haben GLEICHE Priorität,
da gibt es kein Vertun.

Daß *p++ gleichbedeutend ist mit *(p++) liegt daran, daß
die Operatoren dieser Gruppe von rechts her zusammengefasst
werden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Yalu X. schrieb:
>> Nimm eine andere Tabelle, z.B. diese hier:
>>
>>   http://www.difranco.net/cop2220/op-prec.htm
>>
>> Da hat der Postfixinkrementoperator Vorrang vor dem Verweisoperator.
>> *ptr++ ist also das Gleiche wie *(p++).
>
> Das ist jetzt leider falsch.

Klaus, hast du zufällig eine 'offizielle Operator Precedence Table' 
irgendwo rumliegen?

Hier
http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
ist es nämlich auch so, dass postfix ++ und -- höhere Priority haben als 
die präfix Formen.

Würde mich jetzt interessieren, was die offizielle Stellung dazu ist.

Da wir uns hier in den beiden obersten Prioritätenklassen bewegen, wird 
es wohl in der Praxis keinen Unterschied machen. Zumindest ist es mir in 
ein paar Minuten nicht gelungen ein Beispiel zu konstruieren, bei dem es 
einen Unterschied gäbe.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ganz offiziell ist teuer. Aber hier mal noch eine Tabelle, zwar C++ aber 
das ist egal: http://www.cppreference.com/wiki/operator_precedence

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Greifbar habe ich den K&R, siehe 
http://mfgkw.dyndns.org/k+r2_operatoren.jpg.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Im Text auf der Seite vorher steht explizit zu der Tabelle:
"Innerhalb einer Zeile haben Operatoren den gleichen Vorrang"

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob die beiden in der gleichen Prioritätsklasse stehen, oder ob man 
daraus getrennte Klassen macht, ist effektiv egal. Denn die stets mit 
angebenene Assoziativität stellt klar, dass hier "rechts vor links" 
gilt.

Somit sind beide Darstellungen korrekt, aber diejenige mit getrennten 
Klassen für * und ++-postfix sind leichter verständlich. Und für 
besondere Klarheit und Präzision ist die K&R-Referenz nicht bekannt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:

> Somit sind beide Darstellungen korrekt, aber diejenige mit getrennten
> Klassen für * und ++-postfix sind leichter verständlich.

So sehe ich das auch.
Also sind wir ohnehin alle derselben Meinung :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Hier
> http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
> ist es nämlich auch so, dass postfix ++ und -- höhere Priority haben als
> die präfix Formen.

Merkwürdiger- und überraschenderweise scheint sich das bei C++
tatsächlich etwas verschoben zu haben.
Aus dem Stroustruppi:
http://mfgkw.dyndns.org/C++operatoren_a.jpg
http://mfgkw.dyndns.org/C++operatoren_b.jpg

In dem Fall mit *p++ ist es sicher egal.

Aber ich habe den Verdacht, daß man Fälle konstruieren kann,
wo es einen Unterschied zwischen C und C++ gibt.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:

> Aber ich habe den Verdacht, daß man Fälle konstruieren kann,
> wo es einen Unterschied zwischen C und C++ gibt.

Wie eben beschrieben hat sich nicht das Verhalten verschoben, sondern 
die Spezifikation wurde so gestaltet, dass man solche Diskussionen wie 
diese hier nicht mehr führen muss.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mag sein.
Wenn man die alte Operatorentabelle liest, ist sie aber m.E.
ebenso eindeutig.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Klaus, hast du zufällig eine 'offizielle Operator Precedence Table'
> irgendwo rumliegen?

Es gibt keine, zumindest nicht im C99-Standard. Stattdessen sind dort
Priorität und Assoziativität der Operatoren folgendermaßen definiert:
The grouping of operators and operands is indicated by the syntax.⁷¹⁾

In der Fußnote ist das genauer erläutert:
71) The syntax specifies the precedence of operators in the evaluation
    of an expression, which is the same as the order of the major
    subclauses of this subclause, highest precedence first.
    […]
    Within each major subclause, the operators have the same precedence.
    Left- or right-associativity is indicated in each subclause by the
    syntax for the expressions discussed therein.

Zwei unäre Präfixoperatoren op1 und op2 übereinander liegender Priori-
tätsebenen werden in der Grammatik folgendermaßen dargestellt (für Post-
fix- und binäre Operatoren entsprechend):

  b :
    a
    op1 b

  c :
    b
    op2 c

Für binäre Operatoren op1 und op2 innerhalb einer Prioritätsebene wird
die Assoziativität folgendermaßen dargestellt:

linksassoziativ:

  b :
    a
    b op1 a
    b op2 a

rechtsassoziativ:

  b :
    a
    a op1 b
    a op2 b

Da eine entsprechende Darstellung für unäre Operatoren nicht möglich ist
(mir fällt zumindest spontan keine Lösung ein), haben die Standardiseure
zwischen primary-expression und unary-expression ein weiteres
Nichtterminalsymbol (und damit eine weitere Prioritätsebene) namens
postfix-expression eingefügt, so dass die Grammatik vereinfacht¹
folgendermaßen aussieht:

  postfix-expression :
    primary-expression
    postfix-expression ++
    ...

  unary-expression :
    postfix-expression
    * unary-expression
    ...

Damit ist die Auswertereihenfolge von * (Dereferenzierung) und ++ (Post-
inkrement) formal über die Priorität und nicht über die Assoziativität
geregelt, was aber in der Anwendung keinen Unterschied macht. Deswegen
sind zwei unterschiedliche Operatortabellen im Umlauf, die aber letzt-
endlich äquivalent sind.


¹) Ich habe der Übersichtlichkeit halber die Ebene cast-expression
   weggelassen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.