Forum: PC-Programmierung Feld an Vorhandenem Feld hängen C


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Chandler B. (chandler)


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.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Schau dir doch einfach mal an, wie eine verkette Liste (linked list) 
funktioniert.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Oder was man mit der Funktion realloc() machen kann, wenn der Speicher 
fuer die bestehende Struktur mit [mc]alloc "geschaffen" wurde.

Gruss
WK

von Oliver S. (oliverso)


Lesenswert?

Mit realloc hat das nichts zu tun, und auch nichts mit "struct 
erweitern".

Das Stichwort "linked list" fiel ja schon. Dazu gibt's ausreichend viele 
Infos im Netz.

Chandler B. schrieb:
> Ich muss

Manchmal stellt sich dann die Frage: Warum?

Hausaufgaben? RTFM

Nutzung vorhandener Bibliotheken? RTFM

Oliver

: Bearbeitet durch User
von Chandler B. (chandler)


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

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


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

: Bearbeitet durch User
von Klaus W. (mfgkw)


Lesenswert?

Chandler B. schrieb:
> frameTable_ps* frameTable_ps

Chandler B. schrieb:
> frameTable_ps = frameTable_ps;

Das verwirrt mich jetzt auch.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Klaus W. schrieb:
> Chandler B. schrieb:
>> frameTable_ps* frameTable_ps

das ist sicher ein Fehler und soll `Schedule_ts* frameTable_ps` lauten

von Chandler B. (chandler)


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
}

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


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.

von Peter (pittyj)


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.

von Ob S. (Firma: 1984now) (observer)


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.

von Peter D. (peda)


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.

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.