• hallo,

    wollt eine liste machen, die verschiedene structs zulaesst. hab das dann mit union so gemacht:

    da die structs der union alle den selben speicher benuetzen, hab ich mire gedacht, ich kann einfach:

    Code
    List* alist;
    VariableNode* var = bla;
    alist = addListElement(alist, (Data*) var);

    das funktioniert so nun aber leider nicht, dataelement bekommt zwar den pointer, aber nicht die 4 elemente der union.
    Nun hab ich mir ueberlegt einfach:

    Code
    Data* data;
    data->varNode = var;
    alist = addListElement(alist, data);

    da krieg ich aber leider segmentation fault, ganz wo anders (char array das fuers parsen genutz wird). Hab aber ausserdem nichts geaendert, und das hat zuerst funktioniert.

    kann es sein dass ich fuer data auch ein malloc machen muss?
    hab das hinzugefuegt und dann gehts, aber irgendwie kommt mir das wie speicherverschwendung vor. und der ist leider eher knapp.
    gibts irgendeine moeglichkeit wie ich das sonst einfacher machen/haben kann (liste mit unterschiedlichen objecten)?

    bin fuer alle tipps dankbar!

  • danke war sehr schnell, kenn mich aber leider nicht ganz aus. meinst du?

    liste->data->.... gibt mir nun aber keine vorschläge mehr (autovervollständigung).
    muss dann zuerst:
    VarNode bla = (VarNode*)liste->data;
    seh ich das richtig?

  • Wenn du einen void* pointer hast, dann musst du nachher auf den korrekten Datentyp casten, ja.

    Je nachdem was du zur Verfügung hast, könntest es auch mit einem Template versuchen.

  • muss dann zuerst:
    VarNode bla = (VarNode*)liste->data;
    seh ich das richtig?


    Ja. Wenn du dir sicher sein kannst, dass an dieser Stelle liste->data auf einen Knoten vom Typ VarNode zeigt. Du wirst dafür noch irgendeine Art von Datenelement mitschleppen müssen. Dafür gibt es in C mehr oder weniger obskure und fehleranfällige Techniken.

    Je nachdem was du zur Verfügung hast, könntest es auch mit einem Template versuchen.


    Ja, C++ wäre für solche Aufgaben sicher besser geeignet als C. (Andere Sprachen wären noch viel viel besser geeignet...)

    *plantsch*

  • Ja. Wenn du dir sicher sein kannst, dass an dieser Stelle liste->data auf einen Knoten vom Typ VarNode zeigt. Du wirst dafür noch irgendeine Art von Datenelement mitschleppen müssen. Dafür gibt es in C mehr oder weniger obskure und fehleranfällige Techniken

    was muss ich noch mitschleppen? wenn ich meine listen erstelle, weiss ich ja was ich hineingebe... und weiss dann auf was ich casten muss beim wiederherausnehmen. wird das so funktionieren oder sollte ich lieber für jedes struct eine eigene liste machen? oder vielleicht doch mit union wie vorher?

    Zitat

    Ja, C++ wäre für solche Aufgaben sicher besser geeignet als C. (Andere Sprachen wären noch viel viel besser geeignet...)

    muss das ganze leider in c machen...

    danke für die hilfe!

  • was muss ich noch mitschleppen? wenn ich meine listen erstelle, weiss ich ja was ich hineingebe... und weiss dann auf was ich casten muss beim wiederherausnehmen. wird das so funktionieren oder sollte ich lieber für jedes struct eine eigene liste machen?


    OK, wenn in jeder Liste immer nur Knoten desselben Typs sind, dann kannst du einfach die Listen auseinanderhalten. Problematisch wäre es, wenn in einer Liste verschiedene Arten von Knoten sein könnten.

    (Wenn in jeder Liste immer nur Knoten desselben Typs sind, dann kann man statt mit (void *) auch mit Makros arbeiten und hat strenges Typechecking. Manche Leute finden Makros aber doof.)

    Zitat

    oder vielleicht doch mit union wie vorher?


    Bei unions mußt du auch wissen, auf welches Feld du zugreifen willst; das Problem ist dasselbe. Wenn du es bei einer union immer weißt, dann weißt du es bei (void *) auch.

    *plantsch*

  • Ich hab eine Liste mal so implementiert, dass ich eine Struktur "listNode" definiert habe, die ich dann in jeder enthaltenen Struktur an einer definierten Position eingefügt hab

    die Zugriffsfunktionen haben dann jeweils einen Typecast der nodeTypeA bzw. nodeTypB auf listNode durchgeführt. Wenn eine Struktur in mehreren Listen vorhanden sein sollte, hab ich bei der initialisierung des List Roots einen unsigned long int Parameter übergeben, der den relativen Offset der listNode Datenstruktur in den jeweiligen Strukturen erhalten hat (per offsetof) hinzugefügt ...

    Einziger Haken an so einer Implementierung ist natürlich, dass man sowohl mit den Positionen der Listen Navigationsdaten innerhalb des Objekts sehr leicht durcheinander kommt als auch durch Compiler Optimierungen böse Überraschungen erleben könnte ...

  • Einziger Haken an so einer Implementierung ist natürlich, dass man sowohl mit den Positionen der Listen Navigationsdaten innerhalb des Objekts sehr leicht durcheinander kommt


    Tu das Gemeinsame am besten an den Anfang der Struktur, dann mußt du nicht mit Offsets rumtun. Der C-Standard garantiert, daß das Layout von Strukturen mit gleichen Anfangselementen in diesen Elementen identisch ist. Damit kannst du eben direkt (nodeTypeA *) und (nodeTypeB *) auf (listNode *) casten.

    Zitat

    als auch durch Compiler Optimierungen böse Überraschungen erleben könnte ...


    Kann mir da grad kein plausibles Problem ausmalen.

    *plantsch*

  • Tu das Gemeinsame am besten an den Anfang der Struktur, dann mußt du nicht mit Offsets rumtun. Der C-Standard garantiert, daß das Layout von Strukturen mit gleichen Anfangselementen in diesen Elementen identisch ist. Damit kannst du eben direkt (nodeTypeA *) und (nodeTypeB *) auf (listNode *) casten.

    Das ist dann solange möglich, solange jede Struktur nodeTypeA und nodeTypeB genau in einer einzelnen Liste liegt. Die Offsets waren bei mir dann notwendig, weil ich mehrere unterschiedliche Listen (bzw. mit einer ähnlichen Implementierung Bäume) hatte, in denen ein und die selbe Struktur indiziert wurde.


    Kann mir da grad kein plausibles Problem ausmalen.

    Wenn die Struktur (listNode) nicht in jeder Struktur (nodeTypeA, nodeTypeB) gerade am Anfang der Struktur liegt, kann es unter gewissen Umständen zu Problemen mit dem Packing der Strukturen bei der Optimierung kommen (wenn unterschiedliche Datentypen vor den jeweiligen listNode Strukturen liegen).

    Aber stimmt prinzipiell das man das einfach dadurch umgehen kann, dass man die für die Listen bzw. Bäume notwendigen Strukturen einfach an den Anfang der Struktur schreibt

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!