Problem mit union
-
hermes schrieb:
In der srtuct Values muss ich ein Dummy einfügen, tue ich das nicht verändere
ich den Wert von SN (im TXBuffer) wenn ich eine ungerade Zahl nach ResetTestMode
schreibe.Das kauf ich dir so erstmal nicht ab
, du musst noch mehr machen, als das, was du uns erzählst. Zeig mal die Stelle, an der du die Werte in der struct/union schreibst.btw:
Welchen Compiler benutzt du?
-
Das kauf ich dir so erstmal nicht ab
, du musst noch mehr machen, als das, was du uns erzählst. Zeig mal die Stelle, an der du die Werte in der struct/union schreibst.Hast recht, das Problem lag woanders.
-
1. Hast du den Sinn einer Union überhaupt verstanden? Die einzelnen Elemente liegen übereinander im selben Speicherbereich, also ist es logisch, daß sie sich gegenseitig beeinflussen.
2. Ich mag mich ja täuschen, aber der Name "Buffer" dürfte zu Konflikten führen.
-
CStoll schrieb:
1. Hast du den Sinn einer Union überhaupt verstanden?
Hast du den Sinn der Frage überhaupt verstanden?
-
1. Hast du den Sinn einer Union überhaupt verstanden?
Klar habe ich den Sinn einer Union verstanden.
Wenn ich die Membervariable TxData.Values.SN beschreibe wird der Wert
gleichzeitig nach TxData.Buffer.TXBuffer gespeichert, da die Start Adressen
der beiden structs an der gleichen Speicherstelle liegen.
Weiter Mebervariablen der Structure Values werden ebenfalls an die entsprechende
Position nach TXBuffer geschrieben.
Diesen Buffer sende ich dann via RS232 an einen Controller.
Auf der Gegenseite befindet sich dieselbe Union (RXBuffer) mit einem RXBuffer in dem die Daten gelesen werden, das ganze wird dann ja auch gleich wieder
in die MemberVariable RXBuffer.Values.SN geschrieben.Was meinst du den welchen Sinn eine Union hat?
2. Ich mag mich ja täuschen, aber der Name "Buffer" dürfte zu Konflikten führen.
Warum??
-
Kannst du die Anwendung dieser struct/union-Kombination mal in der Praxis vorstellen? So langsma blicke ich nämlich nicht mehr durch, wo dort dein Fehler ist.
hermes schrieb:
2. Ich mag mich ja täuschen, aber der Name "Buffer" dürfte zu Konflikten führen.
Warum??
Weil du ihn doppelt verwendet hast - einmal als typedef für "unsigned char[50]" und einmal als Element der Union.
-
hermes schrieb:
Klar habe ich den Sinn einer Union verstanden.
Wenn ich die Membervariable TxData.Values.SN beschreibe wird der Wert
gleichzeitig nach TxData.Buffer.TXBuffer gespeichert, da die Start Adressen
der beiden structs an der gleichen Speicherstelle liegen.
Weiter Mebervariablen der Structure Values werden ebenfalls an die entsprechende
Position nach TXBuffer geschrieben.Tja, weit gefehlt. Eine Union ist dazu da, Speicher zu sparen. Man soll bei einer union nur auf das zuletzt zugewiesene Feld zugreifen. Zugriff auf die anderen Felder ist nicht durch den Standard definiert.
Der Standard greift einem hier aber zumindest soweit unter die Arme, dass Unions im C-Speicherlayout vorliegen. Sofern dir klar ist, welche Bitmuster du mit der Zuweisung auf ein Union-Element erzeugst, ist das alles für deine Plattform und deinen Compiler in der aktuellen Version definiert (sofern du dich wiederum an das C-Speicherlayout hältst). Ich hoffe dir ist klar, dass der letzte Part eine äußerst brüchige und unportable Angelegenheit ist und deshalb nicht verwendet werden sollte. Anderenfalls kommt es einem reinterpret_cast gleich - mit dem Unterschied, dass du den cast nichtmal mehr hinschreibst. Das nennt sich dann Type-Punting (das Typ-System wird in die Tonne getreten). Sollte man also nur wirklich da anwenden, wo low-level-APIs das von dir erfordern.
Und immer daran denken: "If you lie to the compiler, it will get its revenge (for sure)."
-
Weil du ihn doppelt verwendet hast - einmal als typedef für "unsigned char[50]" und einmal als Element der Union.
Sehe ich ein.
union { struct { unsigned int a; unsigned int b; }Values; struct { unsigned char TXBuffer[50]; }Buffer; }TxData; TXData.Values.a = 0x1234; TXData.Values.b = 0x5678;Nun steht in TXData.Buffer.TXBuffer[0] = 34, [1] = 12, [2] = 78, [3] = 56.
Denn Bufferinhalt sende ich nun via Rs232 zu einem Controller, der folgende
union hatunion { struct { unsigned int a; unsigned int b; }Values; struct { unsigned char RXBuffer[50]; }Buffer; }RxData;nach RxData.Buffer.RxBuffer .
Nun stehen in RxData.Values.a = 0x1234 , ...b = 5678.
Ich erspare mir damit das lästige umkopieren der Values in die Buffer.
-
Und an welcher Stelle hast du nun deine Probleme? Am Ende steht das in den Rx... Elementen, was du vorne in Tx... eingetragen hast.
(btw kannst du Probleme bekommen, wenn du beide Teile auf verschiedenen Systemen laufen hast - der C++ Standard schreibt nicht vor, wie (z.B.) ein unsigned int aufgebaut ist)
PS: Was ich noch verbessern würde: gib der union einen Namen und pack sie in einen gemeinsam verwendeten Header

//defs.h union MsgData { //... }; //Tx.cpp #include "defs.h" MsgData TxData; //Rx.cpp #include "defs.h" MsgData RxData;
-
typedef unsigned char BUFFER[50]; typedef union { struct { unsigned char ClearTestStatus :1; // 1 Done }bits; unsigned char byte; }RESETTESTMODE; union { struct { unsigned int SN; unsigned int Dummy; //Hier muss ich ein Dummy RESETTESTMODE ResetTestMode; //einfügen }Values; struct { BUFFER TXBuffer; }Buffer; }TxData;Das mit dem BUFFER sollte so ausehen.
-
Und wo ist das Problem? in der Union stehen "parallel" zueinander eine struct mit drei Elementen (das letzte ist wieder eine union) und dein char-Buffer - wobei die Verteilung der struct-Bytes in den Puffer-Bereich willkürlich vom Compiler/Prozessor/was-weiß-ich vorgenommen werden kann.
-
(btw kannst du Probleme bekommen, wenn du beide Teile auf verschiedenen Systemen laufen hast - der C++ Standard schreibt nicht vor, wie (z.B.) ein unsigned int aufgebaut ist)
Da das eine auf dem PC 80x86 läuft ist hier ein int natürlich 32 bit breit, es muss
natürlich unsigned short(16Bit) sein, ein Schreibfehler von mir,union { struct { unsigned short a; unsigned short b; }Values; struct { unsigned char TXBuffer[50]; }Buffer; }TxData; TXData.Values.a = 0x1234; TXData.Values.b = 0x5678;Da die zweite Union sich in einem 8Bit Controller
befindetunion { struct { unsigned int a; unsigned int b; }Values; struct { unsigned char RXBuffer[50]; }Buffer; }RxData;ist hier int natürlich 16bit breit.
wobei die Verteilung der struct-Bytes in den Puffer-Bereich willkürlich vom Compiler/Prozessor/was-weiß-ich vorgenommen werden kann.
Wie mir bekann ist stehen die MemberVariablen in einer struct immer der
Reihe nach im speicher.
Ich habe diese frage schon einmal gestellt, es wurde behauptet das dieses
bei jedem Compiler so ist.
Na ja bei dem C++ Bilder sowie den Compiler für den µC ist es jedenfalls
so(im Watch Fenster überprüft).Auf jedenfall funktioniert das ganze so wie ich es gemacht habe.
-
Die Elemente stehen hintereinander im Speicher - aber dazu kommen noch Probleme wie Padding (der Compiler darf Zwischenräume lassen) und big endian vs little endian (Bedeutung der Bits in einem int).
-
Ok, also für mich war(ist) eine Union für meinen Zweck bestens geeigned.
Da es aufgrund dieser Tatsache nicht auf jedem Compiler so läuft, frage
ich mich wofür dann so eine Union da ist.Gebe mal ein praktisches Beispiel.
-
hermes schrieb:
Da es aufgrund dieser Tatsache nicht auf jedem Compiler so läuft, frage
ich mich wofür dann so eine Union da ist.Meinen Post gelesen?

-
Eine Union ist dazu da, Speicher zu sparen. Man soll bei einer union nur auf das ??? zuletzt zugewiesene Feld zugreifen.?????
Verstehe ich nicht ganz, kannst du das mal genauer erklären.
-
Eine besondere Typkonstruktion ist die union. Man könnte sie als Entweder-oder-Verbund bezeichnen. In einer Union werden mehrere Variablen zusammengefasst, von denen nur eine gebraucht wird. Es kann also immer nur eines der angegebenen Elemente verwendet werden. Eine Union nimmt darum so viel Speicher ein, wie das größte seiner Elemente benötigt.
Ok ist schon klar, hast du nicht einen Vorschlag wie man das was ich möchte
anders hinbekommt?