Steh grad wieder voll auf dem Pointer-Schlauch ;-(
ich zimmer mir grad ein kleines Menü zusammen.
Ich weis nicht, wie die die Größe des Array menuItems[] im struct
menuItem ermitteln kann.
Reiner W. schrieb:> ich zimmer mir grad ein kleines Menü zusammen.> Ich weis nicht, wie die die Größe des Array menuItems[] im struct> menuItem ermitteln kann.
gar nicht.
Du müsstest dir einen Member in die Struktur machen, in den du bei der
Initialisierung den Wert reinschreibst.
Ihr erwartet alle zuviel von C. In C ist praktisch nichts irgendwie
dynamisch. Auch wenn die Strukturdefinition erst mal so aussieht, als ob
das so wäre
1
typedefstructmenu{
2
constchar*text;
3
MENUMEMBER_tmenuItems[];
4
}MENU_t;
Das ist eine 'Mogelpackung'. Wenn du sowas hast, dann bist du immer auf
dich alleine gestellt. Der Compiler kann dir da nicht weiter helfen.
Auch nicht mit einem sizeof. Nur durch Betrachten dieser
Strukturdefinition kann niemand sagen, wieviel Speicher tatsächlich für
das Array allokiert wurde. Wenn du die Information brauchst, dann musst
du selber sie dir in die Struktur reinschreiben.
1
typedefstructmenu{
2
constchar*text;
3
uint8_tnrItems;
4
MENUMEMBER_tmenuItems[];
5
}MENU_t;
wodurch diese ganze dynamische Allokierung
1
MENU_tmainMenu={
2
"Main Menu",//Menu Name
3
4,// Anzahl Entries
4
{//Menu Entries
5
{"MenuItem 1",NULL,0},//text, function, keep
6
{"MenuItem 2",NULL,1},
7
{"MenuItem 3",NULL,1},
8
{"zurueck",NULL,0},
9
}
10
};
deutlich an Eleganz verliert, weil du eine Abhängigkeit 2-er Member
hast.
Karl Heinz schrieb:> gar nicht.> Du müsstest dir einen Member in die Struktur machen, in den du bei der> Initialisierung den Wert reinschreibst.
Danke, für die schnelle Antwort. Ich hatte es befürchtet;-(
Hab vorher so gelöst:
1
...
2
typedefstructmenu{
3
constchar*text;
4
MENUMEMBER_t*menuItems[];
5
}MENU_t;
6
...
7
8
menu.menuItems[0]=&menuItem0;
9
menu.menuItems[1]=&menuItem1;
10
menu.menuItems[2]=&menuItem2;
11
...
Da kann ich dann die Größe ermitteln mit
sizeof(menu.menuItems)/sizeof(menu.menuItems[0]) ermitteln.
Was ist denn sinnvoller ?
(habs grad gesehen, das Problem liegt nicht daran, wie ich das Array am
struct festmache, sondern daran, dass das Array ohne Länge deklariert
ist)
Reiner
Reiner W. schrieb:> Was ist denn sinnvoller ?
Sinnvoll wäre es zb, wenn du nicht darauf bestehst, alles in einer
Struktur zu haben
1
typedefstructmenu{
2
constchar*text;
3
uint8_tnrItems;
4
MENUMEMBER_t*menuItems;
5
}MENU_t;
6
7
MENUMEMBER_tmainMenuItems[]=
8
{
9
{"MenuItem 1",NULL,0},//text, function, keep
10
{"MenuItem 2",NULL,1},
11
{"MenuItem 3",NULL,1},
12
{"zurueck",NULL,0},
13
};
14
15
MENU_tmainMenu={
16
"Main Menu",//Menu Name
17
sizeof(mainMenuItems)/sizeof(*mainMenuItems),
18
mainMenuItems;
19
};
da kann dir jetzt wieder der Compiler unter die Arm greifen und per
sizeof die Länge des Arrays ermitteln und in die Struktur eintragen.
Du hast halt einen Pointer mehr im System, mit dem der Zusammenhang der
Menu Beschreibung zu den Items des Menüs hergestellt wird
Karl Heinz schrieb:> Du hast halt einen Pointer mehr im System, mit dem der Zusammenhang der> Menu Beschreibung zu den Items des Menüs hergestellt wird
Danke Karl Heinz für die (wie immer) ausführliche Erklärung!
Hast du eigentlich mal ein Einsteigerbuch geschrieben? Würde ich sofort
kaufen.
Reiner
Reiner W. schrieb:> Danke Karl Heinz für die (wie immer) ausführliche Erklärung!> Hast du eigentlich mal ein Einsteigerbuch geschrieben?
Ja aber hallo! Gleich mal ans Werk machen. :-)
Karl Heinz schrieb:> Ist mir zu viel Stress :-)
Musst doch nur ein paar hundert Threadbeiträge hier zusammenkopieren :-)
Zum Thema: Man könnte auch dafür sorgen, dass das Array der MENUMEMBER_t
immer mit einem Null Wert abgeschlossen ist.
Dann kann man durchiterieren, bzw die Länge ermitteln wie es strlen()
bei einem String macht.
Udo Schmitt schrieb:> Zum Thema: Man könnte auch dafür sorgen, dass das Array der MENUMEMBER_t> immer mit einem Null Wert abgeschlossen ist.> Dann kann man durchiterieren, bzw die Länge ermitteln wie es strlen()> bei einem String macht.
Stimmt, das hab ich auch schon mal gemacht.
Ich hab jetzt .numberOfItems im Struct zugefügt.
Da ich ja die Menüeinträge sowieso von Hand im Struct anlege, kommt es
da auch nicht mehr drauf an.
Udo Schmitt schrieb:> Zum Thema: Man könnte auch dafür sorgen, dass das Array der MENUMEMBER_t> immer mit einem Null Wert abgeschlossen ist.
Wobei (hab ich auch gerade erst gelernt) es sich dann um eine gcc
Extension handeln würde. Im C Standard ist das nicht erlaubt, eine
Struktur mit einem flexible array member zu initialisieren. d.h. man
kann natürlich die Struktur schon initialisieren nur eben den flexible
array member nicht.
Ich seh das pragmatisch so:
C war von Anfang an darauf ausgelegt, dass alles zur Compile-Time eine
fixe und feststehende Größe hat. Egal ob das Arrays oder Strukturen
waren, alles hatte seine Größe und der Compiler konnte die feststellen.
Hatte man keine fixen Größen, dann musste man über Pointer und alloca
oder malloc oder ... gehen. Fixe Größe konnte auch sein, dass der
Compiler Initialisierungen abzählt.
Was ja bis hier her auch noch kein Problem wäre.
Bei Strukturen kommt jetzt noch dazu, dass alle jemals von diesem
Strukturtyp erzeugten Objekte auch die gleiche Größe haben müssen. Denn
wenn dem nicht so wäre, dann würde man in Schwierigkeiten kommen, wenn
man ein Array von diesem Strukturtyp anlegen würde.
Bis dahin war noch alles in Ordnung.
Dann allerdings gab es noch die Fälle, in denen man tatsächlich ein
Strukturobjekt bauen möchte, welches einen variablen Anteil hat. Man
behalf sich mit Krücken, in dem man eine struct definierte, welches als
letzten member ein Array der Länge 1 vorsah (damit dort etwas
Array-ähnliches steht) allokierte allerdings die Objekte immer per
malloc, wobei man eine entsprechende Speichergröße errechnete, so dass
die Datenmenge da rein passt, die man haben wollte. Arrays davon baute
man einfach nicht und wenn dann waren es Pointer Arrays, deren Elemente
dynamisch angelegt wurden.
Womit dann auch ganz automatisch der Themenkreis Initialisierung keiner
war, denn bei dynamischer Allokierung kann man nichts (ausser bei
calloc) initialisieren.
Ab da war dann das meiste nur noch Kosmetik um diesen 'Hack' zu
verschönern. Denn an den grundsätzlichen Problem, dass ein Array keine
Größeninformation mit sich rumträgt, kann man nichts ändern. Da würde
zuviel Code den Bach runter gehen, wenn man da groß umrührt. Man denke
nur an die Fälle, die im Zusammenhang mit Parameterpassing an Funktionen
stehen. Zwischen Arrays und Pointer besteht nun mal in C ein enger
Zusammenhang.
Also kann sich auch ein Strukturobjekt nicht implizit merken, wie gross
sein flexible array member ist. Ganz abgesehen davon, dass das das
Problem der Array Bildung von solchen Strukturen nicht lösen würde. Die
ist ja immer noch davon abhängig, dass alle Strukturobjekte im Array die
gleiche Größe haben.