Dereferenzierung und Postinkrement von Zeiger in einer Zeile

Gast #1638831
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
  }
#1638895
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..??
#1638901
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.
#1638908
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.
#1638914
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.
#1638940
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.
#1638958
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.
#1638963
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.
Moderator #1639150
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.

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