Zeiger auf Variable

OP #813075
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
OP #813151
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?
Persönliche Seite #813168
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".

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