Guten Morgen,
wie kann ich eine Struktur einer Funktion übergebe?
Ziel soll es sein, dass die Funktion WriteToMemory jetzt nicht drei
Parameter für jede einzelne Struktur bekommt. Wie könnte dies mit einem
Übergabeparameter realisiert werden?
Coder schrieb:> wie kann ich eine Struktur einer Funktion übergebe?
Genau wie andere Typen auch, per Kopie oder per Zeiger.
> Ziel soll es sein, dass die Funktion WriteToMemory jetzt nicht drei> Parameter für jede einzelne Struktur bekommt. Wie könnte dies mit einem> Übergabeparameter realisiert werden?
Das heißt, die Funktion soll alle drei Strukturen auf einmal bekommen,
aber nur mit einem Parameter? Dann kannst du diese einfach in einer
übergeordneten Struktur zusammenfassen.
Je nach Situation soll die entsprechende Struktur der Funktion übergeben
werden. Zusammenfassen kann ich leider nicht machen.
Die Daten von der Struktur st_data1 soll nur während Produktion in das
Flash geschrieben werden. Bei den anderen Strukturen entweder permanent
oder ab und zu.
Deinem 'WriteToMemory' musst du eben noch mit einem weiteren Parameter
mitteilen, welcher Teil vom Vorschlag von 'fop' geschrieben werden soll.
Andernfalls brauchst du drei unterschiedliche WriteToMemory-Funktionen,
die du entsprechend aufrufst, weil die drei Structs ja unterschiedlich
sind und du in der Funktion wissen musst, welche Parameter im Struct wie
belegt sind.
Es mag noch Tricks geben, die mir aber nicht bekannt sind.
Es ist nicht so ganz klar, was du eigentlich genau willst. Wie sollen
die Daten geschrieben werden? Als Binärklumpen oder serialisiert? Wohin?
Woran willst du nachher beim lesen erkennen, welche der Strukturen da
drin steht?
Die einfachste Art einer Schreibfunktion wäre eine, die einen void* und
eine Größe als Parameter bekommt. Da kannst du schreiben, was du willst.
Die jeweiligen Daten von den Strukturen soll in ein internes Flash vom
Mikrocontroller byteweise abgelegt werden.
Das mit einem void* als Übergabeparameter wäre eine gute Möglichkeit.
Allerdings brauche ich da natürlich noch die Längenangabe. Dies kann ich
mit sizeof(..) herausfinden.
ich glaube, er möchte immer die übergebene Struktur gespeichert werden
soll.
da würde ich einen Cast auf einen Pointer auf uint8_t und die Länge der
Struktur als Parameter vorsehen.
Coder schrieb:> Danke für die Untersützung. Wie würde dies als Beispiel aussehen?
Wie würdest du eine Funktion schreiben, die als Parameter einen Pointer
auf einen uint8_t-Typ und eine Größenangabe erwartet?
Wie ermittelst du die Adresse einer Struktur?
Wie castest du Typen?
Iwie fehlen mir Informationen um das zu beantworten?!?
Also ich fasse mal zusammen. Du kannst die 3 Structs nicht kombinieren,
weil das 1. Struct konstante Werte beinhaltet. Du kannst aber auch
Struct-Member konstant deklarieren. (siehe https://matt.sh/sytycc)
Dann möchtest du das Struct in einen Speicher schreiben. Was für ein
Speicher das ist, ist erstmal egal. Was wichtig für mich zu wissen wäre,
welche Wortbreite hat der Speicher (ich gehe jetzt mal von 8Bit=1Byte
aus).
Wenn du nun das struct speichern willst, dann kannst du das indem du das
struct in den Type uint8_t umcastest (hat schon ein Vorredner
geschrieben). Das machst du so:
1
typedefstruct{
2
constinta;//can only be set in initialization
3
intb;//can be read and written
4
}new_type;
5
6
voidwrite_to_memory(uint8_t*ptr,unsignedintlen){
7
...
8
}
9
10
intmain(void){
11
...
12
new_typedata_a={5,2};
13
uint8_t*pointer_to_struct=(uint8_t*)&data_a;//cast pointer to struct into uint8_t*
14
unsignedintstruct_len=sizeof(data_a);
15
write_to_memory(pointer_to_struct,struct_len);
16
}
Die Länge deines Structs ist immer gleich. Es sei denn du hast
dynamische Arrays in deinem Struct(wenn das geht, ich glaube aber
schon). Dann musst du natürlcih wissen wie lang dein Struct war beim
abspeichern und die Daten auch genau zuordnen können.
Wenn du ein statisches Struct hast, dann kann es sein dass dein Compiler
Paddings um die einzelnen Variablen hinzufügt. Das sind einfach leere
Bytes um z.B. eine 8Bit Variable auf die 32Bit Wortlänge des Controllers
zu bringen oder sowas. Die sind aber auch immer gleich (bei statischen
Structs).
Das heißt, wenn du ein Struct in den Speicher schreibst und wieder
ausließt, dann kannst due die gelesenen Daten einfach deinem Struct
zuweisen und deine Variablen sollten die richtigen Werte haben.
Wichtig ist heir auch die Reihenfolge. Wenn du die Bytes falsch herum
deinem Struct zuweist, kommt natürlich kauderwelsch raus.
Hoffe es hilft weiter.
Gruß
Tja, Du wolltest zwar "nur" schreiben, aber spätestens beim
Wiederauslesen der Daten wirst Du das Problem haben, dass Du an der
Stelle nicht (mehr) weisst, was Du da eigentlich hingeschrieben hast
(liest Du nun ein st_data1, ein st_data2 oder ein st_data_3?).
Also solltest Du (zumindest) diese Info noch irgendwo hinterlegen.
HildeK schrieb:> Es mag noch Tricks geben, die mir aber nicht bekannt sind.
Es gibt noch die Möglichkeit dies per varargs-Funktion zu machen.
Das nur der Vollständigkeit halber; es soll keine Anregung sein, sowas
hier zu verwenden.
Hallo,
eine Funktion für verschiedene Strukturen geht sowieso nicht. Wird bspw.
key in der Funktion verwendet gibt es Mecker wenn eine Struktur ohne key
übergeben wird.
Ich würde mich auf eine! Struktur für alle einigen, dass erleichtert
vieles. Man muss die Member woanders ja nicht verwenden wenn nicht
benötigt.
Johann L. schrieb:> Es gibt noch die Möglichkeit dies per varargs-Funktion zu machen.
Ja, vielen Dank. Das war es wohl, ich hatte an die Parameterübergabe von
printf gedacht, dort wird es auch mit varargs gemacht (soweit ich mich
erinnere).
Das ist nichts, was ich in meinen Funktionen verwende ... 😀
Eine andere, vielleicht funktionierende Möglichkeit könnte ein union aus
den drei structs sein. Ähnlich wie foo es mit dem Superstruct vorhat.
Könnte gehen, weil die beiden ersten Variablen gleichen Datentyps sind.
Trotzdem muss zur Unterscheidung welcher struct übergeben wurde noch
eine Information hinzugefügt werden.
Egal wie, einer WriteToMemory-Funktion muss das hier klar gemacht
werden:
Coder schrieb:> Die Daten von der Struktur st_data1 soll nur während Produktion in das> Flash geschrieben werden. Bei den anderen Strukturen entweder permanent> oder ab und zu.
HildeK schrieb:> Eine andere, vielleicht funktionierende Möglichkeit könnte ein union aus> den drei structs sein.
Das ist totaler Bruch: Polymorphie-für-Arme.
Da man in C nun mal Funktionen nicht überladen kann, schreibt man 3
Funktionen mit unterschiedlichen Namen zum Serialisieren. Intern rufen
die dann eine vierte auf, die eine byte-weise Serialisierung durchführt.
Wenn das Zeugs an unterscheidlichen Stellen im Flash/EEprom liegt, ist
das Deserialisieren ja auch keine Thema. Andernfalls benötigt man ein
Typ-Marker.
foobar schrieb:> Während die Vorschläge hier immer abstruser werden, benutzt der Rest der> Welt schon sein Jahrzehnten:
Genau so hatte ich es beschrieben, allerdings mit 3 convenience-wrappern
darum:
Wilhelm M. schrieb:> Da man in C nun mal Funktionen nicht überladen kann, schreibt man 3> Funktionen mit unterschiedlichen Namen zum Serialisieren. Intern rufen> die dann eine vierte auf, die eine byte-weise Serialisierung durchführt.
Coder schrieb:> Ziel soll es sein, dass die Funktion WriteToMemory jetzt nicht drei> Parameter für jede einzelne Struktur bekommt.
Wenn Du mit "3" Adresse, Zeiger und Länge meinst:
Coder schrieb:> uint8_t* pointer_to_struct = (uint8_t*) &data_a; //cast pointer to> struct into uint8_t*
Warum eigentlich uint8_t*? Nimm einfach einen void*. Der ist dafür da
und macht den Cast unnötig.
> unsigned int struct_len = sizeof(data_a);
Für Objektgrößen sollte man size_t bevorzugen.
Coder schrieb:> Ich habes mal so umgesetzt wie oben bereits gezeigt wird.
* Wo wird die zugehörige EEPROM-Adresse angegeben?
* was denkst Du bewirkt const bei "a" in der Struktur?
* welchen Sinn haben pointer_to_struct und struct_len (statt direkt
&data_a und sizeof data_a)?
Guten Morgen,
ich Funktion braucht keine Adresse. Es handelt sich um eine spezielle
Lib die den non volatile memory managed. Ich brauche aber noch einen
weiteren Parameter der die Nummer des Objekte übergeben soll.
Coder schrieb:> ich Funktion braucht keine Adresse. Es handelt sich um eine spezielle> Lib die den non volatile memory managed. Ich brauche aber noch einen> weiteren Parameter der die Nummer des Objekte übergeben soll.
schreib einfach was Du hast, was Du brauchst und wie Du es Dir
vorstellst. Wir kennen weder Deine Lib noch Deine Objekte oder Deine
Vorstellungen.