Guten Abend zusammen
Folgende Ausgangslage:
Ich habe eine Strukt a, ein Strukt b, und ein Strukt c
Hier der Aufbau von Strukt
a:
1
unsignedcharAttribut_1a[20];
2
unsignedcharAttribut_2a[1];
b:
1
unsignedcharAttribut_1b[5];
2
unsignedcharAttribut_2b[5];
c:
1
unsignedcharAttribut_1c[5];
2
unsignedcharAttribut_2c[5];
Nun die Frage:
Ist es möglich, dem Attribut_1a von Strukt a die Werte des Gesamten
Stuktes b und c anzuhängen?
Speichermässig sollte es dann so aussehen
--- Attribut_1a ----
Inhalt von Strukt a
Inhalt von Strukt b
--- Attribut_2a ----
Irgend einen zugewiesenen Wert.
Ich hoffe ich versteht was ich fragen möchte :)
Danke
Fabian O. schrieb:> Vielleicht suchst Du ein Union?> struct a {> union a1bc {> unsigned char Attribut_1a[20];> struct bc {> struct b;> struct c;> };> };> unsigned char Attribut_2a[1];> };> Oder vielleicht auch einfach nur:struct a {> struct b;> struct c;> unsigned char Attribut_2a[1];> };
Hmmm ich bin mir nicht ganz sicher ob wir uns richtig verstanden haben
:)
Ich habe nun also im Code diese beiden Strukte initialisiert:
1
structmyStruct_a*StructA;
2
structmyStruct_b*StructB;
3
structmyStruct_c*StructC;
nun möchte ich so etwas machen:
1
myStruct_a->Attribut_1a=myStruct_b+myStruct_c;
Das die so direkt wohl nicht geht ist mir klar.
Es soll quasi der Speicherbereich von myStruct_b und myStruct_c in
das Attribut_1a eingefüllt werden.
Schön ist das allerdings nicht und außerdem gefährlich, wenn Attribut_1a
nicht groß genug ist ...
Wenn Du die Struktur gleich als Union bzw. so definierst, dass sie
Attribute von Typ myStruct_b und myStruct_c aufnehmen kann, geht es ohne
gefährlichen Cast:
1
myStruct_a->Attribut_bc.Attribut_b=*StructB;
2
myStruct_a->Attribut_bc.Attribut_c=*StructC;
bzw.
1
myStruct_a->Attribut_b=*StructB;
2
myStruct_a->Attribut_c=*StructC;
Dir ist übrigens hoffentlich klar, dass Du in dem Beispiel nur Zeiger
auf die Strukturen definiert hast und nicht den Speicher für die
Strukturen selbst?
Fabian O. schrieb:> Das geht, wenn Du den Zeiger auf Attribut_1a in einen Zeiger auf eine> Hilfsstruktur castest:
Danke für die Lösung. Aber wenn ich ein hilfsstruct brauche, dann kann
ich auch gleich wie du gesagt hast
Fabian O. schrieb:> Wenn Du die Struktur gleich als Union bzw. so definierst, dass sie> Attribute von Typ myStruct_b und myStruct_c aufnehmen kann, geht es ohne> gefährlichen Cast:
Eine Union definieren.
Fabian O. schrieb:> Dir ist übrigens hoffentlich klar, dass Du in dem Beispiel nur Zeiger> auf die Strukturen definiert hast und nicht den Speicher für die> Strukturen selbst?
Vielen Dank für den Hinweis.
Nein so wirklich bewusst war mir dies nicht.
Ich bin noch ein wenig Lernbedürftig was Zeiger im Zusammenhang mit
Strukten und Unions angeht.
Eigentlich ist diese methode jedoch vorteilhaft, da diese Speicher
spart.
Andererseits gefählrich, wenn zb. ein Interrupt auf das Strukt in der
Selben Art und weise zugreiffen würde.
Wie sähe es denn aus, wenn ich neuen Speicher mit der Struct Struktur
anlegen würde?
Danke dir.
Claudio Hediger schrieb:> Eigentlich ist diese methode jedoch vorteilhaft, da diese Speicher> spart.
Im Gegenteil, die Zeiger brauchen zusätzlichen Speicher (je Zeiger z.B.
16 Bit = 2 Byte). Um den Speicher, in dem die Struktur selbst liegt,
kommst Du ja nicht rum.
Mal ein ganz allgemeines Beispiel. Zuerst sagst Du dem Compiler, wie die
Strukturen aufgebaut sind. Das braucht noch keinen Speicher, sondern ist
nur eine Information für den Compiler. Ich finde es mit typedef
leserlicher, ist aber Geschmackssache:
1
typedefstruct{
2
uint8_tb1[5];
3
uint8_tb2[5];
4
}b_t;
5
6
typedefstruct{
7
uint8_tc1[5];
8
uint8_tc2[5];
9
}c_t;
10
11
typedefstruct{
12
b_tb;
13
c_tc;
14
uint8_ta2;
15
}a_t;
Als nächstes legst Du die Variablen an. Dabei wird der Speicher für die
Strukturen reserviert. Das hängt jetzt von Deiner Anwendung ab, welche
sie wie oft braucht:
1
a_tmein_a;// belegt 21 Byte
2
b_tmein_b;// belegt 10 Byte
3
c_tmein_c;// belegt 10 Byte
Jetzt kannst Du damit arbeiten:
1
mein_b.b1[0]=23;
2
mein_c.c2[2]=42;
3
[...]
Wenn Du nun den Inhalt von mein_b in mein_a.b kopieren willst, geht das
mit:
1
mein_a.b=mein_b;
Ich vermute mal, dass das schon das ist, was Du eigentlich brauchst.
Aber der Vollständigkeit halber auch noch die Version mit der Union:
Die Deklaration des Typs:
1
typedefstruct{
2
union{
3
uint8_ta1[20];
4
struct{
5
b_tb;
6
c_tc;
7
}bc;
8
}a1_bc;
9
uint8_ta2;
10
}a_t;
Die Definition der Variable ist wie gehabt:
1
a_tmein_a;// belegt ebenfalls 21 Byte
Den Inhalt von mein_b und mein_c an die gewünschten Stellen kopieren:
1
mein_a.a1_bc.bc.b=mein_b;
2
mein_a.a1_bc.bc.c=mein_c;
Der Unterschied zu vorher ist, dass Du in die Struktur a_t statt einem
b_t und einem c_t auch 20 Bytes (uint8_t) am Stück ablegen kannst, auf
die Du per mein_a.a1_bc.a1[x] zugreifst.
Vielen Dank für deinen Beitrag.
Ich denke damit sollte es klappen :)
Ansonsten melde ich mich nochmal :)
//////////////// Edit //////////
Ja da hätte ich noch eine Frage.
Ich habe nun alle structs zu Typedefs gemacht und eine entsprechende
Variable gezogen.
Zuvor hatte ich ein Strukt wie folgt befüllt:
1
myHeader=(structHeader*)Ð_buffer[UDP_DATA];
doch nun klappt das nicht mehr.
1
error: incompatible types in assignment
Wie würde das befüllen einer typedef Variable aussehen?
Danke
Claudio Hediger schrieb:> myHeader = (struct Header*)Ð_buffer[UDP_DATA];
Damit hast Du nicht die Struktur gefüllt, sondern nur einen Zeiger
verändert! Das muss nicht falsch sein, aber es macht
höchstwahrscheinlich nicht das, was Du eigentlich dachtest. Poste also
am besten mal den ganzen (relevanten) Code, sonst ist das Stochern im
Nebel ...
Fabian O. schrieb:> Claudio Hediger schrieb:>> myHeader = (struct Header*)Ð_buffer[UDP_DATA];>> Damit hast Du nicht die Struktur gefüllt, sondern nur einen Zeiger> verändert! Das muss nicht falsch sein, aber es macht> höchstwahrscheinlich nicht das, was Du eigentlich dachtest. Poste also> am besten mal den ganzen (relevanten) Code, sonst ist das Stochern im> Nebel ...
Ja da hast du recht :) ich poste morgen den gesamten relevanten code.
Ich danke dir für deine bisherige unterstützung
entschuldigt, eine etwas unorthodoxe Frage:
Luna unterstützt wie C ja auch Strukturen, wäre rein zum Verständnis
diese Strukturdeklaration hier dasselbe aus obigem Beispiel?:
> myHeader = (struct Header*)Ð_buffer[UDP_DATA];
Da man ja ein bisschen erahnen kann, warum es geht, vielleicht doch noch
ein paar Worte dazu:
Du möchtest wahrscheinlich auf die einzelnen Elemente des UDP-Headers
zugreifen, der Teil des empfangenen Ethernet-Frames in ETH_buffer ist.
Dazu musst Du den Header nicht extra in eine eigene Variable kopieren,
wie ich es oben beschrieben habe. Es reicht, die bereits im Speicher
liegenden Daten anders zu interpretieren.
ETH_buffer ist wohl ein Byte-Array, also z.B. so definiert:
1
uint8_tETH_buffer[1500];
Dort liegen die empfangenen Daten. ETH_buffer{UDP_DATA] dürfte das erste
Byte des UDP-Headers sein. Mit Ð_buffer[UDP_DATA] bekommst Du einen
Zeiger auf dieses Byte, also dessen Speicheradresse.
Man kann diese Speicheradresse aber nicht nur so interpretieren, dass
sie auf das erste Byte zeigt, sondern auch so, dass sie auf den
UDP-Header zeigt. Diese "uminterpretieren" geht in C mit einem Cast.
Dazu muss man C zuerst sagen, wie so ein UDP-Header aussieht:
1
typedefstruct{
2
uint16_tport_source;
3
uint16_tport_destination;
4
uint16_tlength;
5
uint16_tchecksum;
6
}udp_header_t;
Danach erstellt man sich eine Variable, die einen Zeiger auf einen
UDP-Header enthält:
1
udp_header_t*udp_header_zeiger;
In dieser Variable ist nur Platz für eine Adresse (je nach Plattform
z.B. 16 Bit = 2 Byte), nicht für die eigentlichen Daten des UDP-Headers!
Jetzt lassen wir diese Variable auf die Stelle zeigen, an der der
UDP-Header wirklich im Speicher liegt. Dazu müssen wir den Zeiger
Ð_buffer[UDP_DATA], der auf das erste Byte zeigt, in einen Zeiger auf
einen UDP-Header casten:
Und nun kann man über diesen Zeiger auf die einzelnen Elemente des
UDP-Headers zugreifen:
1
udp_header_zeiger->port_source
Hier muss man den Pfeiloperator statt dem Punkt benutzen, weil
udp_header_zeiger eben nicht die Daten selbst enthält, sondern die
Speicheradresse, an der sie stehen.
Und um den Bogen zu vorher noch zu schließen:
Wenn Du nicht die Daten in ETH_buffer uminterpretieren willst, sondern
tatsächlich eine Kopie des UDP-Headers erstellen willst, geht das
natürlich auch.
Variable für den UDP-Header anlegen:
1
udp_header_tmein_udp_header;
Die belegt 8 Byte im Speicher für die ganzen Felder des UDP-Headers. In
diese Variable kann man jetzt die 8 Bytes ab der Stelle
ETH_buffer[UDP_DATA] kopieren. Dazu gibt es zwei Möglichkeiten.
Die erste ist:
Sprich: Kopiere 8 Bytes (die Größe des UDP-Headers) von der Adresse
Ð_buffer[UDP_DATA] an die Adresse &mein_udp_header.
Die andere Möglichkeit geht wieder über einen Cast:
Sprich: Interpretiere die Adresse Ð_buffer[UDP_DATA] als Zeiger auf
einen UDP-Header. Lese die Daten, auf die der Zeiger zeigt
(Dereferenzieren, mit dem *-Operator), und speichere sie in der Variable
mein_udp_header.
Auf die einzelnen Elemente greift man dann ganz normal mit dem Punkt zu:
@Fabian.
Du hast es echt drauf!
Danke vielmals. Auch deine Erklärungen sind sehr verständlich.
Du hast wohl alle meine Fragen beantwortet, das was genau dass, was ich
wissen wollte :)
Tausend Dank!
Carlo schrieb:> Luna unterstützt wie C ja auch Strukturen, wäre rein zum Verständnis> diese Strukturdeklaration hier dasselbe aus obigem Beispiel?:struct b_t> byte b1(5)> byte b2(5)> endstruct>> dim mein_a as a_t>> mein_a.b.b1(1) = 123> ...>> dasselbe?>> Gruß, Carlo
ja, ist dasselbe, mit dem Unterschied, dass bei C mit [..] die
Elementanzahl und bei Luna mit (..) das maximale, nullbasierte
Arrayelement angegeben wird. Du musst also z.Bsp. c1(4) schreiben.
H.
Wenn ich die Auskommentierten Zeilen für die UART Funktion weg mache,
(also die Uart funktion ausführe) funktioniert alles so wie es soll.
Wenn ich hingegen die funktion auskommentiere, werden die Werte den
Variablen nicht zugewiesen!
Der Inhalt im rxPACKET_Buffer ist korrekt.
Woran kann dies liegen?
hier noch die uart funktion:
Claudio H. schrieb:> Achjaa, natürlich habe ich auch noch eine Variable mit dem Zeiger...> Header* myHeader;> RGBPaket* myRGBData;
Problem gelöst.
Es muss so heissen: