Forum: Compiler & IDEs Funktionsparameter mit Pointer


von Net_Hans (Gast)


Lesenswert?

Hallo,
ich habe versucht folgenden Quellcode im AVR-Studio zu simulieren.
Aber die Variable wird nicht wie erhofft hochgezählt.

Kann mir bitte jemand auf die Sprünge helfen, was ich falsch mache?
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <stdint.h>
5
#include <stdlib.h>
6
7
int16_t data;
8
9
void test(int16_t volatile *x){
10
  *x++;
11
}
12
13
int main(void)
14
{
15
  data = 0;  
16
  
17
  while(1)
18
  {
19
    PORTB = data;
20
    test(&data);
21
    PORTB = data;
22
  }
23
}

Danke
mfg Hans

von troll (Gast)


Lesenswert?

Was macht das volatile da?

Mach mal testweise statt
> *x++;
(*x)++;
.

von troll (Gast)


Lesenswert?

Nebenbei bemerkt, es macht nicht viel Sinn sich mit Pointern 
rumzuschlagen wenn die Variable sowieso global ist...

von Net_Hans (Gast)


Lesenswert?

Hallo,

danke das mit den Klammern funktioniert.

In dem Beispiel habe ich erst mal klein angefangen später soll es in die 
Richtung gehen.
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <stdint.h>
5
#include <stdlib.h>
6
7
int16_t data_1,data_2,data_3;
8
9
void test(int16_t volatile *x){
10
  ...
11
  *x++;
12
  ...
13
14
}
15
16
int main(void)
17
{
18
  data_1 = 0;  
19
  data_2 = 10; 
20
  data_3 = 20; 
21
  
22
  while(1)
23
  {
24
    PORTB = data;
25
    test(&data_1);
26
    test(&data_2);
27
    test(&data_3);
28
    PORTB = data;
29
  }
30
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Net_Hans schrieb:
> danke das mit den Klammern funktioniert.

Dafür fehlen sie hier wieder:

> *x++;

von Hmm (Gast)


Lesenswert?

Erzähl mal bitte warum der Zeiger volatile sein soll? Noch eins übrig 
gehabt? :-)

von troll (Gast)


Lesenswert?

Net_Hans schrieb:
> Hallo,
>
> danke das mit den Klammern funktioniert.
Dann will ich auch erklären warum: Es liegt an der Operatorenpräzedenz 
(wie schreibt man das?). ++ wird vor * ausgewertet, du inkrementierst 
also erst den Pointer und nimmst dann den Wert davon, machst aber 
nichts weiter damit. (Was nebenbei bemerkt auch keine gute Idee wäre, 
vagabundierende Pointer können schnell Mist machen). Mit den Klammern 
änderst du die Reihenfolge der Auswertung.

> In dem Beispiel habe ich erst mal klein angefangen später soll es in die
> Richtung gehen.
Da fehlen die Klammern. Außerdem ist das volatile da imho überflüssig 
und wie oben geschrieben, solange die Variablen (da kann ein volatile 
durchaus Sinn machen wenn Interrupts im Spiel sind) global sind brauchst 
du gar keine Pointer.

von Net_Hans (Gast)


Lesenswert?

ups ... ja Copy/Pase Fehler ...

Es muss natürlich
1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <stdint.h>
5
#include <stdlib.h>
6
7
int16_t data_1,data_2,data_3;
8
9
void test(int16_t volatile *x){
10
  ...
11
  (*x)++;
12
  ...
13
14
}
15
16
int main(void)
17
{
18
  data_1 = 0;  
19
  data_2 = 10; 
20
  data_3 = 20; 
21
  
22
  while(1)
23
  {
24
    PORTB = data;
25
    test(&data_1);
26
    test(&data_2);
27
    test(&data_3);
28
    PORTB = data;
29
  }
30
}

lauten.

Das volatile hatte ich nur drin, weil ich es in einem anderen Beitrag so 
gesehen hatte ... dort hatten sie geschrieben, das es ein Muss bei der 
Arbeit mit Pointern in Funktionsparametern wäre...

von Hmm (Gast)


Lesenswert?

>Das volatile hatte ich nur drin, weil ich es in einem anderen Beitrag so
gesehen hatte ... dort hatten sie geschrieben, das es ein Muss bei der
Arbeit mit Pointern in Funktionsparametern wäre...

Poste mal einen Link? War das hier im Forum? Unwidersprochen? In diesem 
Kontext?

Jedenfalls ist das hier, in dieser Situation unnötig. In der 
Artikelsammlung gibt es, soweit ich mich erinnere, einen ausführlichen 
Artikel über Zweck und Anwendung von volatile.

Ach ja: http://www.mikrocontroller.net/articles/Volatile

von Karl H. (kbuchegg)


Lesenswert?

Hmm schrieb:

> Jedenfalls ist das hier, in dieser Situation unnötig. In der
> Artikelsammlung gibt es, soweit ich mich erinnere, einen ausführlichen
> Artikel über Zweck und Anwendung von volatile.
>
> Ach ja: http://www.mikrocontroller.net/articles/Volatile

Und noch ausführlicher hier
FAQ: Was hat es mit volatile auf sich


Edit: gerade gesehen - im Artikel ist ja auch ein Link auf den FAQ 
Eintrag.

von Karl H. (kbuchegg)


Lesenswert?

Net_Hans schrieb:

> Das volatile hatte ich nur drin, weil ich es in einem anderen Beitrag so
> gesehen hatte ... dort hatten sie geschrieben, das es ein Muss bei der
> Arbeit mit Pointern in Funktionsparametern wäre...

Das kann nur jemand geschrieben haben, der selber keine Ahnung davon 
hatte, was es mit volatile auf sich hat.

von Hmm (Gast)


Lesenswert?

>Edit: gerade gesehen - im Artikel ist ja auch ein Link auf den FAQ
>Eintrag.
Ts ts ts. Das kost' 'n Salzburger Nockerl. Schlabber.

von troll (Gast)


Lesenswert?

troll schrieb:
> Dann will ich auch erklären warum: Es liegt an der Operatorenpräzedenz
> (wie schreibt man das?). ++ wird vor * ausgewertet, du inkrementierst
> also erst den Pointer und nimmst dann den Wert davon, machst aber
> nichts weiter damit.
Moment, das ist doch falsch! :-( Du nimmst den Wert vom Pointer, 
verwirfst ihn und inkrementierst dann den Pointer. Oder? Karl Heinz, 
Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

troll schrieb:
> troll schrieb:
>> Dann will ich auch erklären warum: Es liegt an der Operatorenpräzedenz
>> (wie schreibt man das?). ++ wird vor * ausgewertet, du inkrementierst
>> also erst den Pointer und nimmst dann den Wert davon, machst aber
>> nichts weiter damit.
> Moment, das ist doch falsch! :-( Du nimmst den Wert vom Pointer,
> verwirfst ihn und inkrementierst dann den Pointer. Oder?

(ich geh mal davon aus, dass du mit Wert vom Pointer die 
Derefenzierung meinst)

Richtig.
In
  x++
ist der Wert des Ausdrucks, der Wert von x vor der Inkrementierung. Und 
es ist nicht näher festgelegt, wann denn eigentlich die Inkrementierung 
tatsächlich stattgefunden haben muss. Alles was wir wissen ist, dass 
dieser Nebeneffekt (das eigentliche Inkrementieren gilt als Nebeneffekt) 
vor dem nächsten Sequence-Point (in diesem Fall das Ende des Statements, 
also der ;) stattgefunden haben muss. Aber wann genau, ist nicht 
festgelegt. Daher ist das Ergebnis von

   x = 8;
   i = x++ + x++;

auch undefined, weil nicht klar ist, wann genau die beiden Inkrements 
auf dieselbe Variable statt finden.

von troll (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> (ich geh mal davon aus, dass du mit Wert vom Pointer die
> Derefenzierung meinst)
Ja.

> Richtig.
Danke. War ein langer Tag...

von Hmm (Gast)


Lesenswert?

>Moment, das ist doch falsch! :-( Du nimmst den Wert vom Pointer,
>verwirfst ihn und inkrementierst dann den Pointer. Oder? Karl Heinz,
>Hilfe!

Durchaus nicht. Der Wert des Zeigers wird eigentlich nicht direkt 
benutzt, sondern dem Compiler mit dem '*' gesagt, dass er nicht den 
Zeiger, sondern das worauf er zeigt inkrementieren soll.

Aber Karl Heinz kann das vielleicht noch viel schöner schreiben. :-)

von Net_Hans (Gast)


Lesenswert?

Wo ich das gelesen habe, weiß ich nicht mehr... es waren dann doch zu 
viele Foreneinträge die ich gelesen habe. ...

Aber danke noch mal für die Hinweise zu volatile. Ich arbeite die jetzt 
erst mal durch.

mfG Hans

von Karl H. (kbuchegg)


Lesenswert?

Hmm schrieb:
>>Moment, das ist doch falsch! :-( Du nimmst den Wert vom Pointer,
>>verwirfst ihn und inkrementierst dann den Pointer. Oder? Karl Heinz,
>>Hilfe!
>
> Durchaus nicht. Der Wert des Zeigers wird eigentlich nicht direkt
> benutzt, sondern dem Compiler mit dem '*' gesagt, dass er nicht den
> Zeiger, sondern das worauf er zeigt inkrementieren soll.

Dann musst du es als

   (*x)++

schreiben. ++ bindet stärker als *

Beispiel:
Diese Operation kommt zb in der Ausgabe eines Strings vor
1
void lcdString( const char* str )
2
{
3
  while( *str )
4
    lcdChar( *str++ );
5
}

*str wird an lcdChar übergeben und str wird inkrementiert.

von Hmm (Gast)


Lesenswert?

Der Wert vom Pointer ist der Pointer! Im allgemeinen wird das so 
ausgedrückt. (Soweit ich weiss).
Im Unterschied dazu steht das worauf der Zeiger zeigt.
In unserem Fall, wird der "Wert" auf den der Zeiger zeigt, nicht 
verworfen, denn er muss ja um eins erhöht werden.

Karl Heinz: Mit Dir bin ich in diesem Thread garnicht zufrieden. :-)

von Hmm (Gast)


Lesenswert?

Karl Heinz schrub:
>Dann musst du es als

>   (*x)++

>schreiben. ++ bindet stärker als *

Dann hat sich die Frage auf den Fall ohne Klammer bezogen. Habe das 
anders verstanden. :-{
Aber dennoch wird da auch nichts verworfen.

von Karl H. (kbuchegg)


Lesenswert?

Hmm schrieb:
> Der Wert vom Pointer ist der Pointer! Im allgemeinen wird das so
> ausgedrückt. (Soweit ich weiss).

Ihr meint beide dasselbe und troll hat einen Fehler gemacht.
Da allerdings eine andere Interpretation als Derferenzieren in diesem 
Zusammenhang keinen Sinn ergeben hätte, hab ich ihn dazu genötigt, 
klarzustellen was er meint.

>
> Karl Heinz: Mit Dir bin ich in diesem Thread garnicht zufrieden. :-)

:-)

von Karl H. (kbuchegg)


Lesenswert?

Hmm schrieb:

> Dann hat sich die Frage auf den Fall ohne Klammer bezogen. Habe das
> anders verstanden. :-{

Ausgangspunkt war ja auch diese Aussage

>> Dann will ich auch erklären warum: Es liegt an der Operatorenpräzedenz
>> (wie schreibt man das?). ++ wird vor * ausgewertet, du inkrementierst
>> also erst den Pointer und nimmst dann den Wert davon, machst aber
>> nichts weiter damit.


Und die ist definitiv falsch.

Operator Precedence hat erst mal nichts mit tatsächlicher 
Auswertereihenfolge zu tun.

von Hmm (Gast)


Lesenswert?

>Und die ist definitiv falsch.

>Operator Precedence hat nichts mit tatsächlicher Auswertereihenfolge zu
>tun.

Na ja. Das wage ich dann doch zu bezweifeln, wenn auch der Vorrang 
letztlich im Verein mit der Bindungsrichtung (Assoziativität) der 
Auswertereihenfolge bestimmt. Alleine also ist der Vorrang nicht 
entscheidend, aber man kann, glaube ich, nicht sagen, das es nichts 
damit zu tun hat.

Aber offen gesagt, glaube ich das wir beide wissen wovon wir reden. Ein 
bisschen Verwirrung um Worte.

von Karl H. (kbuchegg)


Lesenswert?

Hmm schrieb:
>>Und die ist definitiv falsch.
>
>>Operator Precedence hat nichts mit tatsächlicher Auswertereihenfolge zu
>>tun.
>
> Na ja. Das wage ich dann doch zu bezweifeln, wenn auch der Vorrang
> letztlich im Verein mit der Bindungsrichtung (Assoziativität) der
> Auswertereihenfolge bestimmt. Alleine also ist der Vorrang nicht
> entscheidend, aber man kann, glaube ich, nicht sagen, das es _nichts_
> damit zu tun hat.

OK. Nichts ist vielleicht etwas stark ausgedrückt.
Aber es ist besser also zu sagen, dass sie sie bestimmt.

In

  i = bar() * baz() + foo();

ist nicht festgelegt in welcher Reihenfolge die Funktionen aufgerufen 
werden. Auch wenn * stärker bindet als +, kann der Compiler trotzdem 
entscheiden, dass er foo() als erste Funktion aufrufen will. Jede 
beliebige Reihenfolge der Funktionsaufrufe ist möglich.

Gerade Neulinge messen hier der höheren Precedence gerne eine Bedeutung 
bei, die sie nicht hat.

> Aber offen gesagt, glaube ich das wir beide wissen wovon wir reden. Ein
> bisschen Verwirrung um Worte.

Eben. Drumm lassen wirs gut sein. Ok?

von Hmm (Gast)


Lesenswert?

Karl Heinz schrab:
>Gerade Neulinge messen hier der höheren Precedence gerne eine Bedeutung
>bei, die sie nicht hat. (...) Jede
>beliebige Reihenfolge der Funktionsaufrufe ist möglich.

Da gebe ich Dir recht. Das ist genau der Punkt, denke ich, den man 
Anfängern klar machen muss.
Die Tabelle mit dem Vorrang und der Assoziativität bezieht sich genau 
und nur auf die Ausführung der darin genannten "primitiven" 
Operatoren. Aber nicht auf die Auswertung der Operanden.

>Eben. Drumm lassen wirs gut sein. Ok?

OK.  :-)

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.