Feld an Vorhandenem Feld hängen C

OP #7546280
Lesenswert?

Hllo, ich habe ein Problem und hoffe hier auf einen hilfenden rat.

Ich muss einer Funktion eine Struktur übergeben. Allerdings habe habe ich nur einen Pointer davon und muss die Struktur immer erweitern (also neue Daten hinten drann hängen)

1
typedef struct
2
{
3
  uint8_t id;
4
  uint8_t flags;
5
  uint8_t frameLength;
6
}frameCfg_ts;
7

8
typedef struct
9
{
10
  frameCfg_ts* frameTable_ps;
11
  uint8_t nofFrames;
12
}Schedule_ts;

Lokal habe ich mir eine Variable erstellt

1
Schedule_ts scheduleCfg_s;

Jetzt benötige ich eine Funktion, wo ich daten an frameTable_ps dranhängen kann.

1
void scheduleCfgAttach_v(frameTable_ps* frameTable_ps, uint8 nofFrames)
2
{
3
  frameTable_ps = frameTable_ps;
4
  scheduleCfg_s.nofFrames += nofFrames;
5
}

Beim ersten aufruf funktioniert es ja noch. aber wenn die Funktion ein weiteres mal aufgerufen wird, steht an der stelle wo der Pointer drauf zeigt ja schon was drinn. Wie kann ich hinten etwas dranhängen? Wo kann man sich ja mit scheduleCfg_s.nofFrames ausrechnen. Ich weiß halt nur nicht wie ich es hinschreiben muss.

OP #7546318
Lesenswert?

Oliver S. schrieb:

Chandler B. schrieb:

Ich muss

Ich muss, da die Bibliothek die ich verwende eine fertige konfiguration benötigt. Da es bei uns variable sein kann haben wir bisher vorgefertigte Listen genommen. Hier wurde für jede Kombination eine liste erstellt und beim Aufstart abgeprüft welche genommen werden muss.

Da jetzt aber mehrere module kommen, die alle ihr eigenen FrameTable haben, wird das mit den vorgefertigeten Tables zu umständlich

(Firma: Torrox.de) #7546337
Lesenswert?

Chandler B. schrieb:

Wie kann ich hinten etwas dranhängen?

Allein aus der Deklaration von Schedule_ts ergibt sich, dass es sich wohl eher um ein dynamisches array handelt. Mit nofFrames hast Du die derzeitige Anzahl der Elemente im array. Du brauchst Speicher für nofFrames zusätzliche Elemente.

In C macht man das wohl mit realloc: https://en.cppreference.com/w/c/memory/realloc

P.S.: Eine verkettete Liste kann es nicht sein.

Edit: Typos

OP #7546389
Lesenswert?

Klaus W. schrieb:

Chandler B. schrieb:

frameTable_ps* frameTable_ps

Chandler B. schrieb:

frameTable_ps = frameTable_ps;

die Funktion sollte so aussehen

1
void scheduleCfgAttach_v(frameCfg_ts* frameTable_ps, uint8 nofFrames)
2
{
3
  scheduleCfg_s.frameTable_ps = frameTable_ps;
4
  scheduleCfg_s.nofFrames += nofFrames;
5
}

oder die anzahl der Frames mit in der Struktur

1
void scheduleCfgAttach_v(Schedule_ts* frameTable_ps)
2
{
3
  scheduleCfg_s.frameTable_ps = frameTable_ps->frameTable_ps;
4
  scheduleCfg_s.nofFrames += frameTable_ps->nofFrames;
5
}
(Firma: Torrox.de) #7546422
Lesenswert?

Chandler B. schrieb:

die Funktion sollte so aussehen

1
...
2
>

oder die anzahl der Frames mit in der Struktur

1
...
2
>

Bevor Du Dich total verzettelst, hilft es ggf. einmal die Dokumentation der Funktion zu schreiben. Dann ist Dir vielleicht viel besser klar, was die Funktionen machen sollen. Danach kann man dann auch überlegen, ob die Namen für die Funktionen gut gewählt sind.

Königsdisziplin: Du überlegst Dir auch, wie Du die Funktionen testen möchtest und schreibst die Tests ggf. sogar bevor Du die Funktionen selbst implementierst (wie sieht so eine Datenstruktur initial aus? Welche Operationen habe ich auf der Datenstruktur? Welche Sonderfälle gibt es dabei etc.).

Um Funktionen gut testen zu können, ist es vorteilhaft, keine Seiteneffekte zu haben. In Deinem Fall würde das bedeuten, dass Du auf scheduleCfg_s nicht direkt in der Funktion zugreifst, sondern auch diese Struktur als Parameter übergibst.

#7546597
Lesenswert?

Man kann das alles händisch über realloc(), eventuelll umkopieren etc, machen. Man kann auch eine verkette Liste anlegen, Beispiele dafür gibt es genug in diversen C Büchern. Da muss man aber immer mit den Pointern klar kommen, und genau wissen, was man tut.

Ich hatte darauf irgendwann keine Lust mehr, und benutze nur noch C++ std::vector. Damit kann man wunderbar was dranhängen, oder löschen. Kann die Strukturen selber in den Vector eintragen, oder da nur die Pointer nehmen.

Ich bin damit schneller, und habe auch wesentlich weniger Fehler, weil kein Pointer mal ins Nirwana zeigt.

https://en.cppreference.com/w/cpp/container/vector

Und beim Kompilieren statt gcc kann man einfach g++ aufrufen.

(Firma: 1984now) #7546678
Lesenswert?

Oliver S. schrieb:

Mit realloc hat das nichts zu tun

Doch, natürlich kann man das auch damit machen. Hat halt neben dem Nachteil, dass ReAllocs Zeit kosten und den Speicher in großen Blöcken fragmentieren, den Vorteil, dass alle Operationen, die keine Erweiterung des Arrays erfordern, eben auf ein Array angewendet werden können, was fast immer viel effizienter ist als dieselben Operationen auf eine (auch: Double-)LinkedList anzuwenden.

Der Overhead sowohl beim Speicherbedarf (zusätzlich: die Node) als auch beim Rechenzeitaufwand für's Iterieren mit einem Haufen Indirektionen fällt einfach weg.

Und das Problem bei der Erweiterung kann man mit "Exp2-Erweiterung" und vernünftigen Startwerten bezüglich der erforderlichen Kapazität recht gut in den Griff bekommen. Die Libs aller höheren Programmiersprachen machen das genau so.

Oder, je nach konkreter Ausprägung, auch mal als "Chimäre". Das hängt dann primär davon ab, wie groß der Payload ist, aber auch von den anzuwendenden Operationen. Dann gibt es u.U. einen Speicherbereich, der als Array nach den o.g. Prinzipien verwaltet wird und die eigentlichen Nutzdaten beinhaltet, und einen zusätzlichen Speicherbereich, der die Nodes einer LL aufnimmt, aber auch nach den o.g. Prinzipien verwaltet wird. Sowas trifft man vor allem bei Sachen, die einerseits viel Payload haben, abdererseits aber auch schnell nach vielen verschiedenen Kriterien sortiert werden sollen. Sprich: z.B. bei Datenbanken.

Letzlich kochen halt alle mit Wasser. Unbegrenzte Resourcen gibt es nicht. Und deswegen auch keine für alle Anwendungsfälle optimale Lösung.

#7547330
Lesenswert?

Chandler B. schrieb:

Wie kann ich hinten etwas dranhängen?

Gar nicht. Du legst ein Array der Struct an, z.B. für 10 Einträge und füllst dieses nacheinander. Sind alle Einträge belegt, erweiterst Du mit realloc das Array. Zur Verwaltung des Arrays hast Du noch 2 Variablen für die reservierte und die belegte Anzahl. Die belegte Anzahl kann man auch mit einem ungültigen Element kennzeichnen (Leerstring, Nullpointer, NAN). Ist zur Compilezeit die maximale Anzahl bekannt, kann man die natürlich fest reservieren.

Eine Linked List benutzt man nur, wenn die Elemente sortiert werden müssen, z.B. bei einem Scheduler nach der Ablaufzeit.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren