Funktionsparameter mit Pointer

Gast #3083299
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
Gast #3083321
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
}
Gast #3083349
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.
Gast #3083351
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...
Gast #3083359
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
#3083377
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.
Gast #3083404
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!
#3083412
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.
Gast #3083417
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. :-)
Gast #3083419
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
#3083426
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.
Gast #3083428
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. :-)
Gast #3083437
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.
#3083441
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. :-)

:-)
#3083448
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.
Gast #3083462
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.
#3083478
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?
Gast #3083510
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.  :-)

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