Forum: Compiler & IDEs Zeiger auf Variable


von Chris R. (mrgreen)


Lesenswert?

Hallo,
ich steh grad bezüglich eines Zeigers etwas auf dem Schlauch.

Ich habe in einem Array im Flash einen Zeiger auf eine Variable liegen.
Diese will ich dann lesen oder verändern.

uint8_t get_selection(uint8_t id) {
  uint8_t *foo = pgm_read_word(&menu[id].old_selection);
  return *foo;
}

Ändern der Variablen:
void set_selection(uint8_t id, uint8_t value){
  uint8_t *t = pgm_read_word(&menu[id].old_selection);
  *t = value;
}

wobei menu.old_selection vom Typ uint8_t* ist.
Initialisiert habe ich old_selection mit &bar, wobei bar natürlich auch 
uint8_t ist.

So klappt es aber nicht. Aber pgm_read_word liefert mir doch lediglich 
die Adresse der Variablen zurück, auf die menu.old_selection zeigt.
Das muss ich doch dann de-referenzieren, um auf den Inhalt dieser 
Variablen zu kommen??

Gruß
Mr.Green

von Stefan B. (stefan) Benutzerseite


Lesenswert?

In

return *foo;

ist doch deine Dereferenzierung (*), um auf den Inhalt zu kommen.

Du solltest mehr Code angeben: Wie legst du menu[] an, wie speicherst du 
Werte darin und wie willst du die angegebenen Funktionen im späteren 
Code nutzen.

von Chris R. (mrgreen)


Lesenswert?

Das Menü bau ich aus einem struct auf:

uint8_t sel_on_off; (die ist global, über ein extern)

typedef struct {
  uint8_t id,
    next,
    prev,
    parent,
    child;
    char name[MENU_STRING_LENGTH];
    uint8_t type;
    uint8_t int_part,
      fract_part;
    uint32_t max_int;
    void ( *fkt_pointer )( void );
  uint8_t *old_selection;
  uint32_t *old_int;
  uint16_t *old_fract;

} menu_t;

Menu ist im Flash und logischerweise fest kodiert:
menu_t menu[40] PROGMEM = { [...]
{31,   28,    30,    4,      31,     "LangeAuswahl4",        TYPE_TEXT, 
0, 0, 0, 0 &sel_on_off}};

Auf den Inhalt von sel_on_off will ich dann lesen bzw. schreibend 
zugreifen.
Dazu hatte ich mir die Funktionen oben ausgedacht, die dem Compiler aber 
nicht so recht schmecken wollen.
Das verunsichert mich etwas, weil die doch von der Theorie her so 
funktionieren sollten, oder nicht? Durch das pgm_read_word(...) erhalte 
ich doch erst die Adresse, an der dann der Inhalt von sel_on_off liegt.
Oder ist da ein Denkfehler?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich sehe keinen Denkfehler. Der kann aber noch in dem Code stecken, der 
die Funktionen get_selection() und set_selection() verwendet.

> menu_t menu[40] PROGMEM = { [...]
> {31,   28,    30,    4,      31,     "LangeAuswahl4",        TYPE_TEXT,
> 0, 0, 0, 0 &sel_on_off}};
            ^
Wenn das (^) im Originalcode auch so ist, ist das ein fataler Fehler für 
dein Programm.

von Chris R. (mrgreen)


Lesenswert?

Ne da ist natürlich ein Komma.
Da stand ein Funktionszeiger, der für meine Frage aber nicht relevant 
ist :)

Muss ich denn vielleicht noch casten?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Simuliert auf dem Atmega8 wie erwartet:
1
#include <avr/io.h>
2
#include <inttypes.h>
3
#include <avr/pgmspace.h>
4
5
#define MENU_STRING_LENGTH 32
6
#define TYPE_TEXT 2
7
8
uint8_t sel_on_off;
9
10
typedef struct {
11
  uint8_t id,    next,    prev,    parent,    child;
12
  char name[MENU_STRING_LENGTH];
13
  uint8_t type;
14
  uint8_t int_part, fract_part;
15
  uint32_t max_int;
16
  void ( *fkt_pointer )( void );
17
  uint8_t *old_selection;
18
  uint32_t *old_int;
19
  uint16_t *old_fract;
20
} menu_t;
21
22
menu_t menu[2] PROGMEM = { 
23
  {31, 28, 30, 4, 31, 
24
   "LangeAuswahl4", 
25
   TYPE_TEXT, 
26
   0, 0, 
27
   0, 
28
   0, 
29
   &sel_on_off,
30
   0,
31
   0
32
  }
33
};
34
35
uint8_t get_selection(uint8_t id) {
36
  uint8_t *foo = (uint8_t *) pgm_read_word(&menu[id].old_selection);
37
  return *foo;
38
}
39
40
void set_selection(uint8_t id, uint8_t value){
41
  uint8_t *t = (uint8_t *) pgm_read_word(&menu[id].old_selection);
42
  *t = value;
43
}
44
45
int main(void)
46
{
47
  uint8_t dummy;
48
  
49
  sel_on_off = 23;
50
51
  dummy = get_selection(0);
52
53
  if (dummy == sel_on_off)
54
    dummy = 1;
55
  else
56
    dummy = 0;
57
58
  set_selection(0, 42);
59
60
  dummy = get_selection(0);
61
62
  if (dummy == 42)
63
    dummy = 1;
64
  else
65
    dummy = 0;
66
67
  while(1);
68
}

Der Cast (uint8_t *) beseitigt nur eine Warnung, ist aber an dieser 
Stelle durchaus "legal".

von Chris R. (mrgreen)


Lesenswert?

Wow danke für die Arbeit!!
An den Simulator habe ich gar nicht gedacht und mir den Kopf zerbrochen, 
wie ich das testen könnte :/

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.