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


von noips (Gast)


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?
1
uint8_t *PtrSPI_RecBuff;
2
PtrSPI_RecBuff = (uint8_t*) &SPI_RecBuff;
3
4
for (i=0; i < sizeof SPI_RecBuff; i++) {
5
    while (!(UCB1IFG&UCTXIFG));   // USCI_B1 TX buffer ready?
6
    UCB1TXBUF = 'a';              // turn on master for clock signal
7
    while(UCB1STAT&UCBUSY);       // wait until char is received
8
    *PtrSPI_RecBuff++ = UCB1RXBUF;
9
  }

von Klaus W. (mfgkw)


Lesenswert?

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

ja

von noips (Gast)


Lesenswert?

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

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

von Hc Z. (mizch)


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++.

von Yalu X. (yalu) (Moderator)


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++).

von Daniel V. (danvet)


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?
>
>
1
> uint8_t *PtrSPI_RecBuff;
2
> PtrSPI_RecBuff = (uint8_t*) &SPI_RecBuff;
3
> 
4
> for (i=0; i < sizeof SPI_RecBuff; i++) {
5
>     while (!(UCB1IFG&UCTXIFG));   // USCI_B1 TX buffer ready?
6
>     UCB1TXBUF = 'a';              // turn on master for clock signal
7
>     while(UCB1STAT&UCBUSY);       // wait until char is received
8
>     *PtrSPI_RecBuff++ = UCB1RXBUF;
9
>   }
10
>

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..??

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

von Karl H. (kbuchegg)


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.

von Klaus W. (mfgkw)


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.

von Karl H. (kbuchegg)


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.

von (prx) A. K. (prx)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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

von (prx) A. K. (prx)


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.

von Karl H. (kbuchegg)


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 :-)

von Klaus W. (mfgkw)


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.

von (prx) A. K. (prx)


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.

von Klaus W. (mfgkw)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


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:
1
The grouping of operators and operands is indicated by the syntax.⁷¹⁾

In der Fußnote ist das genauer erläutert:
1
71) The syntax specifies the precedence of operators in the evaluation
2
    of an expression, which is the same as the order of the major
3
    subclauses of this subclause, highest precedence first.
4
    […]
5
    Within each major subclause, the operators have the same precedence.
6
    Left- or right-associativity is indicated in each subclause by the
7
    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.

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.