Forum: Mikrocontroller und Digitale Elektronik Problem mit Pointer in Structure


von Vincent H. (vinci)


Lesenswert?

Hallo

Ich hab eine kurze Frage bezüglich Pointern und Structures und seh 
scheinbar vor läuter Bäumen (& und *) den Wald nicht mehr...

Beispiel an Hand eines "2-dimensionalen String Arrays":
1
// Struktur für Strings
2
typedef struct
3
{       const char *text;
4
}Point;
5
6
// Struktur für Gesamtobjekt
7
typedef struct
8
{  struct Point *points
9
        uint8 row;
10
        uint8 column;
11
}Menu;
12
13
// Generieren eines 2d String Arrays
14
Point myPoints[Y][X]
15
{ {"dies",
16
   "ist",
17
   "ein",
18
   "Beispiel"
19
  },
20
21
  {"usw.",
22
   "usf."
23
  }
24
};
25
26
// Generieren der Gesamtstruktur
27
Menu myMenu = {&myPoints, 0, 0};


Soweit so gut. Nun sollte eine Struktur existieren, die 2x chars und 
einen Pointer für mein "2d-Stringfeld" besitzt? Nur wie greife ich nun 
auf einen String aus diesem Feld zu?
1
const char *foo;
2
foo = myMenu.points...;

& * ** -> . ?

von Peter II (Gast)


Lesenswert?

ich überblick es zwar gerade nicht vollständig aber ich galaube das geht 
so nicht.

Denn in points muss ja ein Zeiger auf eine Struktur rein, du speicherst 
aber dort schon den Zeiger auf den String. Ich glaube nicht das man 
diese sache überhaupt auf einen schlag Initalisierne kann.

Warum überhaupt erst den Zeiger auf die Struct?

Der zugriff sollte so gehen

foo = myMenu.points->text

von Ralf G. (ralg)


Lesenswert?

Vincent Hamp schrieb:
> Nur wie greife ich nun
> auf einen String aus diesem Feld zu?

Da müsste ich auch überlegen ;-)
Warum der Umweg über die Struktur Point?
1
const char myPoints[Y][X];
...reicht das nicht?

von Karl H. (kbuchegg)


Lesenswert?

Peter II hat Recht.
Du hast da eine Unsauberkeit im Strukturaufbau.
1
typedef struct
2
{  struct Point *points

dieser Pointer 'points' kann auf EINEN struct Point zeigen oder auf ein 
1-dimenionales ARRAY von struct Point's. Dies deshalb weil in C ein 
syntaktischer Zusammenhang zwischen Arrays und Pointern existiert. Was 
aber nicht sauber ist, ist wenn du diesen Pointer auf ein 2D Array von 
struct Point's zeigen lassen willst. Klar, mit Casts kann man das alles 
hinbiegen, aber es ist nicht besonders sinnvoll.

Die Frage, der man sich am Anfang stellen sollte lautet: Was versprichst 
du dir von diesem 2D Array? Es bringt dir an dieser Stelle nichts 
sondern macht die Dinge nur komplizierter.

Ansonsten, die Frage nach den Zugriffen:
Mal dir die Datenstruktur auf, die du aufgebaut hast. Aus den 
entsprechenden Diagrammen kann man dann ganz leicht die Zugriffssyntax, 
ausgehende von der Variablen die man hat, ablesen.


Aber erst mal würd ich die Datenstruktur verändern. Auch hier wieder: 
mit einer kleinen Skizze, wie die Dinge zusammenhängen sollen, kann man 
auch gut entscheiden, wie sinnvoll die Datenstruktur ist. Wenn die 
Skizze schon nicht sauber aussieht, kann man meistens davon ausgehen, 
dass auch die entstehende Datenstruktur Probleme machen wird.

von Rolf M. (rmagnus)


Lesenswert?

Der Pointer-Typ ist schon falsch. Er muß vom Typ Zeiger auf den 
Array-Element-Typ sein.
1
Point myPoints[Y][X]
ist aber quasi ein Array aus Arrays. Der Element-Typ des äußeren Arrays 
ist nicht struc t Point, sondern struct Point [X]. Dein Zeiger in Menu 
müßte so ausssehen:
1
  struct Point (*points)[X];
und der Zugriff sähe so aus:
1
foo = myMenu.points[0][0];

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:

> ist aber quasi ein Array aus Arrays. Der Element-Typ des äußeren Arrays
> ist nicht struc t Point, sondern struct Point [X]. Dein Zeiger in Menu
> müßte so ausssehen:
>
1
>   struct Point (*points)[X];
2
>

Eben. Und genau hier liegt das Problem. Da das Ganze offenbar ein 
Menüsystem werden soll, und es im Regelfall ja mehrere unterschiedliche 
Menüs gibt, ist das X kein fixer Wert, sondern von Menü zu Menü 
verschieden.

von Noname (Gast)


Lesenswert?

Dieser Codeabschnitt sollte eigentlich sowieso nicht fehlerfrei 
kompilieren:
1
// Struktur für Strings
2
typedef struct
3
{       const char *text;
4
}Point;
5
6
// Struktur für Gesamtobjekt
7
typedef struct
8
{
9
        struct Point *points  // hier gibts zwei Fehler
10
        uint8 row;
11
        uint8 column;
12
}Menu;

Zum einen fehlt ein Semikolon, zum anderen hast Du garkeine struct 
namens Point definiert. Du hast vielmehr einen Typ namens Point 
definiert. Dann kann der Typname anstelle jedes anderen nativen Typs 
stehen, das Schlüsselwort struct ist falsch:

1
// Struktur für Gesamtobjekt
2
typedef struct
3
{
4
        Point *points;
5
        uint8 row;
6
        uint8 column;
7
}Menu;

Was uns dahin bringt hier immer wieder um kompilierbaren Code zu 
bitte.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Dann sowas vielleicht:
1
typedef struct
2
{  
3
  Menu * SubItems;
4
  char   Text[15];
5
}MenuEntry;
6
7
8
typedef struct
9
{  
10
  integer ItemCount;
11
  MenuEntry * Items;
12
}Menu;
13
14
MenuEntry Menu1Tx[3] = {{NULL, "AA"}, {NULL, "ABC"}, {NULL, "Hallo"}};
15
Menu Menu1 = {3, &Menu1Tx};
16
MenuEntry Menu2Tx[3] = {{NULL, "AB"}, {NULL, "ABD"}, {NULL, "Halli"}};
17
Menu Menu2 = {3, &Menu2Tx};
18
19
MenuEntry MenuMainTx[2] = {{&Menu1, "GA"}, {&Menu2, "GBC"}};
20
Menu MenuMain = {2, &MenuMainTx};
Irgend jemand weiß sicher wie man die gegenseitigen Verweise dieser 
beden Strukturen richtig löst.
Man kann nun noch Funktionspointer mit auf nehmen, dann kann man anhand 
vom Klick direkt die Funktion starten.
Jedenfalls hat man so unendlich viele Untermenü Möglichkeiten.

von Vincent H. (vinci)


Lesenswert?

Erstmals danke für die vielen Antworten.
Hab nun verstanden, dass der Ansatz nicht zielführend, und mein Wissen 
über Strukturen und Pointer ein wenig Auffrischung bedurfte.

Der ursprüngliche Gedanke war eigentlich, Menütexte in Feldern 
zusammenzufassen um deren Einträge übersichtlicher zu gestalten und 
diese schnellstmöglich abändern zu können.

Hab dann aber recht schnell gesehen, dass das wenig Sinn macht, da Menüs 
sowieso "Punkt für Punkt" abgearbeitet werden müssen. Hab mich dann für 
die klassische Variante einer Struktur entschieden, die einen Pointer 
auf einen String im ROM, einen Funktionspointer, sowie Variablen für die 
absolute Lage des gewählten Menüpunkts enthält.

ps: Der Code war übrigens, abgesehen vom ; , mit Hitech C PICC sehr wohl 
kompilierbar.

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.