Forum: Compiler & IDEs Verschachtelte Strukturen und Arrays anlegen


von Jochen (Gast)


Lesenswert?

Hallo!

Vorne Weg: Ein Array kann ich doch so definieren und deklarieren:
1
int werteArray[] = { 1, 2, 3, 4};

Wenn ich einen Strukturbaum habe, der wie folgt aussieht (Pseudocode):
1
 typedef struct _s_Structa
2
{
3
   float a;
4
   float b;
5
} Structa, *pStructa;
6
7
typedef struct _s_Structb
8
{
9
   int aa;
10
   int bb;
11
   Structa arrayVonA[]; /* länge zu Beginn nicht bekannt */
12
   int arrayInts[]; /* länge zu Beginn nicht bekannt */    
13
} Structb;

Wie kann ich eine Variable im Code direkt definieren und deklarieren?
1
Structb meineVariable = { /*aa=*/1,
2
                             /*bb=*/2,
3
                             { { /*a=*/3.6f,
4
                                 /*b=*/4.7f
5
                               }, 
6
                               { /*a=*/5.8f,
7
                                 /*b=*/6.9f
8
                               }
9
                             },
10
                             { 10, 20, 30, 40, 50 }
11
                           }

Bei der Struktur Structb sagt der Compiler er, dass die Größe von 
arrayVonA und arrayInts nicht bekannt sind.
Wie kann ich mein Problem lösen?

Danke für die Hilfe.

Jochen

von Karl H. (kbuchegg)


Lesenswert?

Jochen schrieb:

> typedef struct _s_Structb
> {
>    int aa;
>    int bb;
>    Structa arrayVonA[]; /* länge zu Beginn nicht bekannt */
>    int arrayInts[]; /* länge zu Beginn nicht bekannt */
> } Structb;
> [/c]

Das geht nicht

Du musst hier damit arbeiten, dass du in die Struktur einen Pointer 
reinmachst, und das Array von Structa Elementen extra anlegst

von Karl H. (kbuchegg)


Lesenswert?

1
typedef struct _s_StructA
2
{
3
   float a;
4
   float b;
5
} StructA;
6
7
typedef struct _s_StructB
8
{
9
   int      aa;
10
   int      bb;
11
   StructA* arrayVonA;
12
   int*     arrayInts;
13
} StructB;
14
15
16
StructA myAValues[] = {
17
   { 1.0,  1.5 },
18
   { 2.0,  2.8 },
19
   { 3.0, -4.5 }
20
};
21
22
int myIntValues[] = { 5, 6, 7 };
23
24
StructB MyObject = { 25, 42, MyAValues, MyIntValues };

von Karl H. (kbuchegg)


Lesenswert?

Jochen schrieb:


> Bei der Struktur Structb sagt der Compiler er, dass die Größe von
> arrayVonA und arrayInts nicht bekannt sind.

Logisch.

Beantworte einfach mal, nur für dich selber, folgende Frage:

Deine ursprüngliche Strukturdefinition und gegeben dieser Code
1
void foo( Structb* pObj )
2
{
3
  pObj->arrayInts[0] = 5;
4
}

von der Adresse in pObj an gezählt, wieviele Bytes nach Beginn dieses 
Objektes beginnt denn das Array arrayInts im Speicher? Egal für welches 
Structb Objekt.

Du bist millionenfach intelligenter als der Compiler und kannst die 
Frage nicht beantworten. Wenn du die Frage nicht beantworten kannst, wie 
soll das dann der Compiler können?


Du siehst in dem hier etwas, was es nicht ist.
1
int werteArray[] = { 1, 2, 3, 4};

Das hier ist nicht irgendeine Form von magisch dynamischen Array.
Das steht eigentlich
1
int werteArray[4] = { 1, 2, 3, 4};
nur dass die der Compiler als besonderen Service anbietet, dass du die 4 
in diesem Fall weglassen kannst, indem der Compiler die Anzahl der 
Initialisierungen zählt. Das geht aber nur deshalb, weil der Compiler 
weiß, was ein int ist, und wieviel Speicherplatz ein einzelner int 
belegt. Daher kann man hier in einem Rutsch ein Array von int anlegen 
und den Compiler den dafür notwendigen Speicherplatz anhand der 
Initialisierungen festlegen lassen.
Aber mehr steckt da nicht dahinter. Da wird nicht irgendwo magisch 
Information abgelegt, dass dieses Array jetzt mit 4 Elementen erzeugt 
wurde und dieses hier
1
int andereWerte[] = { 42, 27, 19, 15, -8 };
mit 5. In beiden Arrays ist jeder einzelne int immer gleich gross. Nur 
die Größe der kompletten Arrays unterscheidet sich. In
1
T variable[8];

wobei T für irgendeinen beliebigen Datentyp steht (also auch 
Strukturen!) muss die Größe für T bekannt sein! Und es muss für jeden 
Datentyp (also auch für selbstgeschriebene Strukturen!) möglich sein auf 
diese Art ein Array zu erzeugen. Daher kann deine Strukturdefinition 
nicht akzeptiert werden, weil sie eben genau diese Voraussetzung, eine 
bekannte und konstante Größe zu haben, nicht erfüllt.


In
1
struct s
2
{
3
  int a;
4
  int b;
5
  int c[5];
6
  int d;
7
};
muss jeder Member eine eindeutige Adresslage in Bezug auf den Anfang des 
Arrays haben und auch eine eindeutig festgelegte Größe. Und zwar 
unabhängig davon, was dann konkret in einem struct s Objekt abgelegt 
wird. Ob du im c Member dann nur 3 int speicherst anstelle der 5, die 
möglichen wären, das bleibt dir überlassen, aber JEDES struct s Objekt 
hat erst mal ein Array von 5 int im c-Member. Und das muss auch so sein, 
weil der Compiler ja abgesehen von der eigentlichen Variablendefinition 
bei der Verwendung der Struktur ja nicht wissen kann, wieviele Array 
Elemente du dann wirklich angelegt hast - an dieser Stelle muss das 
konstant und für alle struct s Objekte gleich sein.

Was du natürlich tun kannst, du kannst dann ein Array von struct s 
Obekten anlegen und dort dann wieder den Compiler die Initialisierungen 
zählen lassen
1
struct s Mys[] = {
2
   { 1, 2, { 0, 1, 2, 3, 4 }, 42 },
3
   { 8, 0, { 6, 7, 3, 0, 0 }, 23 }
4
};
Aber jedes einzelne der struct s Objekte in diesem Array hat den 
gleichen Aufbau und muss ihn auch haben, damit man bei
1
    Mys[1].c[3] = 5;
errechnen kann, welches Bytes ab Beginn des Mys Arrays an gerechnet bei 
dieser Zuweisung betroffen sind. Und das geht nur, wenn alle Objekte im 
Array die gleiche Größe haben. (Denn das muss ja auch möglich sein, wenn 
man die Variablendefinition nicht sieht! Nur aus der Strukturdefinition, 
der Anweisung und der Startadresse des Arrays im Speicher muss man 
errechnen können, wo im Speicher die Manipulation stattfindet. Denn was 
anderes hast du in Funktionen meistens nicht)


Denk dir einfach immer: Der Compiler kann nicht zaubern. Wenn du etwas 
nicht errechnen kannst, dann kann es der Compiler auch nicht.


Einfach mal ein wenig darüber nachdenken, warum die Dinge so sind wie 
sie sind. Dann wird vieles klarer und einiges verliert diesen 
Geheimnisvoll-Nimbus.

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.