Forum: PC-Programmierung malloc struct in c


von Christian (Gast)


Lesenswert?

Hallo.

Fuer folgende 2-dimensionale Struktur moechte ich Speicher
mittels malloc allokieren.
Die Groesse von Struct x u. y werden zur Laufzeit ermittelt.

Ist das Allokieren der Struktur, quasi von innen nach aussen,
so korrekt?

 m->y1->x1 = (x) malloc(sizeof(x*x_size));
 m->y1     = (y) malloc(sizeof(y*y_size));
 m         = (matrix) malloc(sizeof(matrix));

 typedef struct
 {
       int a;
 }x;

 typedef struct
 {
      x * x1;
 }y;


 typedef struct
 {
      y * y1;
 }matrix;

matrix *m;

Gruss
Christian

von Promeus (Gast)


Lesenswert?

Das wird Dir um die Ohren fliegen weil der Pointer m noch nicht 
zugewiesen ist.

Grüsse,
R.

von Christian (Gast)


Lesenswert?

Wenn ich aber zuerst m mittels malloc zuweise,habe ich doch
noch nicht die korrekte Groesse fuer m ermittelt,
da diese sich ja erst durch x_size und y_size ergibt.

Bin ratlos.

Christian

von imon (Gast)


Lesenswert?

Ich hoffe deine structuren sind stark vereinfacht denn, so hast du 
letzten endes ein int, welcher über 3 indirecktions ebenen angesprochen 
werden muss.


Das allocieren muss du genau anders herum machen von aussen nach innen.
denn
m->y1->x1 = (x) malloc(sizeof(x*x_size));

hier exestiert werder ein m noch ein y1 welche dereferenziert werden 
kann.
Der cast vor den malloc ist ersten falsch und ausserdem überflüssig in 
C.

Im gegenteil es gibt vielle welche Ihn für gefährlich halten. das 
sizeof, ist auch falsch, du willst sicher die groesse des Pointer auf x 
, mal der anzahl der elemente.


ich schlage daher folgendes vor
1
struct _matrix {
2
     int x;
3
     int y;
4
     struct _matrix *next; // nur als beispiel;
5
} matrix_t; // _t wird gerne als hinweis auf einen datentype welcher mit typedef erzeugt wurde angehaengt. 
6
7
matrix_t *m;
8
9
m = malloc(sizeof(*m) * anzahl); 
10
m->next = malloc( sizeof(*matrix->next)); // um die Reihenfolge zu zeigen.

von Udo S. (urschmitt)


Lesenswert?

Und warum legst du nicht einfach xs*ys Felder an?
Speichergröße: xs*ys*sizeof(Feldtyp)

Zum Element x, y kommst du dann mit der Berechnung:

Offset(x,y) = x*xs + y

von test (Gast)


Lesenswert?

Christian schrieb:
> Wenn ich aber zuerst m mittels malloc zuweise,habe ich doch
> noch nicht die korrekte Groesse fuer m ermittelt,
> da diese sich ja erst durch x_size und y_size ergibt.
>
> Bin ratlos.
>
> Christian

Nein, sizeof ist Erstens sowieso konstant zur Compilezeit. Außerdem hat 
die Größe von einem Objekt vom Typ matrix nichts mit der größe der Daten 
hinter den enthaltenen Pointern zu tun, es ist (auf der jeweiligen 
Architektur) immer gleich groß.

Du musst deine Matrix also von außen nach innen allokieren.

Weiterhin sind die aufrufe von malloc für x und y falsch:
1
 m->y1     = (y) malloc(sizeof(y*y_size));

-->
1
 m->y1     = malloc(sizeof(y)*y_size);

von test (Gast)


Lesenswert?

test schrieb:
> m->y1     = malloc(sizeof(y)*y_size);

ach kacke:

 m->y1     = malloc(sizeof(y*) * y_size);

von Udo S. (urschmitt)


Lesenswert?

Udo Schmitt schrieb:
> Offset(x,y) = x*xs + y

Ist natürlich Blödsinn, unter der Annahme, daß man die Elemente E(x,y) 
folgendermassen ablegt
E(0,0), E(1,0), ..., E(xs, 0), E(0,1), ..., E(xs,1), E(0,2), ..., ..., 
E(xn,yn)

müsste es heissen
Offset(x,y) = x + y*xs

Sorry

von Karl H. (kbuchegg)


Lesenswert?

Christian schrieb:

> Bin ratlos.

Eine Möglichkeit der Ratlosigkeit Herr zu werden ist es, sich Papier und 
Bleistift zu nehmen und einfach mal aufzuzeichnen, was du eigentlichg 
erzeugen willst.

Im Endeffekt soll sowas rauskommen
1
   m          (matrix-Objek)        ( y-Objekte)        (x-Objekte)
2
   +---+      +---+                 +---------+         +---+---+---+---+
3
   |  o------>| o------------------>|    o------------->|   |   |   |   |
4
   +---+      +---+                 +---------+         +---+---+---+---+
5
                                    |    o--------+
6
                                    +---------+   |   +---+---+---+---+
7
                                                  +-->|   |   |   |   |
8
                                                      +---+---+---+---+

(Ob diese Komplett-Struktur jetzt sinnvoll ist oder nicht, lass ich mal 
dahingestellt)

Ich hab jetzt nur 2 Y-Objekte eingezeichnet und jeweils 4 X-Objekte. Die 
Zahlen spielen aber keine besondere Rolle, denn im Endeffekt sind das ja 
die x bzw. y Werte, die du vorgegeben hast.

So. Jetzt, da du weißt, wie das Ziel aussehen soll, wie kannst du es 
erreichen. Am Anfang hast du nichts ausser einer Variablen m
1
    m
2
    +---+
3
    |   |
4
    +---+

In welcher Reihenfolge muss jetzt was allokiert werden, damit du dich 
auf dein Ziel zubewegst?

Lass dich von dem Gedanken leiten, dass du immer erst mal eine 
Speicherfläche brauchst, damit du darin einen Pointer abspeichern 
kannst. Wenn du irgendwas mittels malloc neu erzeugst, brauchst du 
bereits vorhandenen Speicher um dort die Adresse einzutragen. In der 
Zeichnung bedeutet das: Du brauchst erst mal ein Rechteck, ehe du einen 
Pfeil auf ein neues Rechteck zeichnen kannst. Denn der Pfeil kann nicht 
im leeren Raum beginnen.

Sieht man sich das Ziel an, dann geht da zuerst mal ein Pointer auf ein 
Matrix Objekt. Also wirst du das erst mal allokieren müssen, denn diese 
matrix Objekt benötigst du, um darin den Pointer auf die y-Objekte 
ablegen zu können. (Die y-Objekte benötigst du wiederrum um darin dann 
die Pointer auf die x-Objekte abzulegen.)

Also
1
    m = malloc( sizeof( matrix ) );

Damit hast du diesen Zustand
1
   m          (matrix-Objek)
2
   +---+      +---+
3
   |  o------>|   |
4
   +---+      +---+

Wie gehts weiter?
Schau auf die Zeichnung, was du erreichen willst. Vom matrix Objekt geht 
ein Pfeil aus zu einem Array von y-Objekten. Also wirst du die als 
nächstes allokieren. Der Pfeil soll beginnen im Matrix Objekt und zwar 
im Struktur-Member y und du brauchst ein Array mit einer gewissen Anzahl 
an y-Objekten
1
    m = malloc( sizeof( matrix ) );
2
    m->y = malloc( y * y_size );

Gut. Damit hast du bis jetzt das hier erzeugt
1
   m          (matrix-Objek)        ( y-Objekte)
2
   +---+      +---+                 +---------+
3
   |  o------>| o------------------>|         |
4
   +---+      +---+                 +---------+
5
                                    |         |
6
                                    +---------+

Wieder: Blick auf die Zeichnung, wie es weiter geht.
Von jedem einzelnen der y-Objekte soll ein weitere Pfeil ausgehen zu 
einem x-Objekt, wobei ein x-Objekt wiederrum ein Array von Elementen 
ist.

Also
1
    m = malloc( sizeof( matrix ) );
2
    m->y = malloc( anzahl_y * sizeof( y ) );
3
4
    for( i = 0; i < anzahl_y; ++i )
5
      m->y->x[i] = malloc( anzahl_x * sizeof( x ) );

Wenn du das mal in die Zeichnung nachträgst und aus jedem der einzelnen 
y-Objekte einen Pfeil zu den jeweils neu allokierten Arrays 
einzeichnest, dann landest du bei
1
   m          (matrix-Objek)        ( y-Objekte)        (x-Objekte)
2
   +---+      +---+                 +---------+         +---+---+---+---+
3
   |  o------>| o------------------>|    o------------->|   |   |   |   |
4
   +---+      +---+                 +---------+         +---+---+---+---+
5
                                    |    o--------+
6
                                    +---------+   |   +---+---+---+---+
7
                                                  +-->|   |   |   |   |
8
                                                      +---+---+---+---+


Hoppla! Das ist aber genau die Komplettstruktur, die du erzeugen 
wolltest.

UNterschätze nie die Macht, die dir Papier und Bleistift geben um dir 
Gedankengänge und Abläufe klar zu machen!

von Christian (Gast)


Lesenswert?

Danke an alle fuer eure Unterstuetzung.

Hab mir Zettel und Stift genommen und die Sache durchdacht.
Denke soweit es begriffen zu haben.

Tolles Forum.

Gruss

Christian

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.