Zeiger auf nichtinitialisierte Struktur, aber wie?

OP #1594541
Hallo C-Gemeinde, ich weiss einfach nicht wonach ich noch suchen soll. 
Was mir einfiel, brachte mich nicht wirklich weiter...

Bin gerade dabei eine Menüstruktur für einen µC zu schreiben. Dabei 
möchte ich gern das Prinzip der verketteten Liste nutzen. Nun habe ich 
aber das Problem, das ich auf Strukturen zeigen muß die noch nicht 
Initialisiert sind. Gibt es dafür in C eine Lösung? Ich könnte natürlich 
alle Menüeinträge in eine Struktur schreiben, das Ganze wird aber bei 
größeren Menütiefen extrem unübersichtlich. Außerdem muß man zum 
Einfügen eines neuen Menüpunktes alle nachfolgenden Menü-Zeiger ändern, 
was die Sache nicht unbedingt Fehlerunanfälliger macht.
1
#define ANZAHL_TASTEN 4
2

3
/*grundlegender datentyp */
4
typedef struct m{ struct m  *upmen;            /* Menü eine Ebene höher, falls vorhanden */
5
                  struct m  *prev;            /* Das vorhergehende Menü dieser Ebene */
6
                  struct m  *next;            /* Das nächste Menü dieser Ebene */
7
                  struct m  *submen;          /* Untermenü, falls vorhanden */
8
                  char      *mtxt;            /* Menütext */
9
                  void      (*mfun)(struct m**);    /* Menüfunktion, falls vorhanden */
10
                  char      *mdat;            /* Menüdaten */
11
                                              /* Die diesem Menüpunkt zugeordneten Tastenfunktionen */
12
                  void      (*tastfun[ANZAHL_TASTEN])(struct m**);  
13
                }MENU;
14

15
// Submenü 1            
16
MENU sm1[]={  {&omu[0], &sm1[0], &sm1[1], NULL, "Menu 1.1", dumfun, NULL, {curup, curdwn, upmen, dumfun}},
17
              {&omu[0], &sm1[0], &sm1[2], NULL, "Menu 1.2", dumfun, NULL, {curup, curdwn, upmen, dumfun}},
18
              {&omu[0], &sm1[1], &sm1[3], NULL, "Menu 1.3", dumfun, NULL, {curup, curdwn, upmen, dumfun}},
19
              {&omu[0], &sm1[2], &sm1[3], NULL, "Menu 1.4", dumfun, NULL, {curup, curdwn, upmen, dumfun}}};
20

21
// Oberste Menüebene
22
MENU omu[]={  {NULL, &omu[0], &omu[1],  sm1, "Menu 1  ", dumfun, NULL, {curup, curdwn, dumfun, submen}},
23
              {NULL, &omu[0], &omu[2], NULL, "Menu 2  ", dumfun, NULL, {curup, curdwn, dumfun, dumfun}},
24
              {NULL, &omu[1], &omu[3], NULL, "Menu 3  ", dumfun, NULL, {curup, curdwn, dumfun, dumfun}},
25
              {NULL, &omu[2], &omu[3], NULL, "Menu 4  ", dumfun, NULL, {curup, curdwn, dumfun, dumfun}}};
26

27

28
/* Das vorhergehende Menü dieser Ebene */
29
void curup(MENU **men)
30
{
31
  MENU *m;
32
  m = (*men)->prev;
33
  if (m)
34
    *men = m;
35
}
36

37
/* Das nächste Menü dieser Ebene */
38
void curdwn(MENU **men)
39
{
40
  MENU *m;
41
  m = (*men)->next;
42
  if (m)
43
    *men = m;
44
}
45

46
/* Untermenü */
47
void submen(MENU **men)
48
{
49
  MENU *m;
50
  m = (*men)->submen;
51
  if (m)
52
    *men = m;
53
}
54

55
/* Menü eine Ebene höher */
56
void upmen(MENU **men)
57
{
58
  MENU *m;
59
  m = (*men)->upmen;
60
  if (m)
61
    *men = m;
62
}
63

64
/* Displaytext anzeigen */
65
void display (MENU **men)
66
{
67
  sendStringSPI((*men)->mtxt);
68
}
69

70

71
MENU *zeile;
72

73
int main(void)
74
{
75
  zeile = omu;
76

77
  while (1)
78
  {
79
    taste = get_key();
80
    if(taste)
81
    {
82
      zeile->tastfun[taste-1](&zeile);
83
      zeile->mfun(&zeile);
84
      display(&zeile);
85
    }
86
  }
87
  return 0;
88
}

Mein Problem ist nun konkret, das ich im Array sm1[] auf om[] verweisen 
möchte, welches aber zu diesem Zeitpunkt noch gar nicht existiert.
1
MENU sm1[]={  {&omu[0],...
Weiß jemand Rat?

Ach ja, das Programm hier muß jetzt nicht 100%ig lauffähig sein. Habe 
ich nur schnell aus meiner Anwendung zusammenkopiert. Es soll nur den 
Sachverhalt verdeutlichen

Viele Grüße,
Steffen
Das Problem mit dem Hauptmenü habe ich in meinem Wettbewerbsbeitrag von 
2008, Tinykon, dadurch gelöst, dass es kein Hauptmenü gibt, auf das zur 
Compilierzeit verwiesen wird.
Die Datenstruktur von Tinykon ist der hier vorgestellten Menüstruktur 
ähnlich (Menüpunkte in doppelt verketteter Liste, Tastatur im 
Zeigerarray, usw), allerdings sind die Menüebenen streng hierarchisch 
dem jeweils aufrufenden Menü untergeordnet, es gibt keinen Rückzeiger, 
der aus dem Untermenü auf das aufrufende Menü zurückzeigt.
Da alle Menüeinträge vom gleichen Datentyp sind, gelangt man zum 
gewünschten Untermenü durch rekusiven Aufrauf der (Menü)Startfunktion, 
der der Zeiger auf das gewählte Untermenü übergeben wird. Zur 
übergeordneten Menüebene gelangt man zurück, in dem man die 
Startfunktion einfach verlässt. Der Compiler sorgt für den richtigen 
Ablauf.
Natürlich funktioniert diese Methode nur, wenn der Zeiger auf das 
übergeordnete Menü auf dem Stapel abgelegt wird, pro Menüebene ein 
Zeiger.

mfg
OP
> Hc Zimmerer
1
extern MENU omu[];

Danke für den Tipp, das ist des Rätsels Lösung! Funktioniert perfekt, 
jetzt kann's ans Eingemachte gehen.

> G. O.
Tatsächlich entstammen 90% der Funktionalität des Menüs deinem Tinykon. 
Dafür ein großes Dankeschön! Vor allem die Funktionszeiger sind genial 
gelöst. Wenn man es erst mal begriffen hat, extrem Übersichtlich und 
Wartungsfreundlich :-) Allerdings möchte ich in der Main() mehrere 
Prozesse abarbeiten, also habe ich es an meine Bedürfnisse angepasst. Es 
ist ja im Prinzip nur ein Zeiger mehr! Dadurch spart man sich aber die 
Rekusivität. Die Menüfunktion wird nur bei Bedarf aufgerufen und kehrt 
in die Main() zurück.

MfG

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.