mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Neue Frage zu Union in 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.
Autor: BL (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

eine Frage an die C-Profis:

Ich habe eine Union für die Uhrzeit gemacht.

typedef union
{
    unsigned short long uns24;
    unsigned char v[3];
    struct
    {
        unsigned char sekunde;
        unsigned char minute;
        unsigned char stunde;
    };
}S_M_H_Time;

In die wird ein RTCC reingelesen und das funktioniert soweit auch alles. 
Jetzt will der Kunde Wochenprogramme haben, also muß aus dem RTCC auch 
der Wochentag rausgelesen werden. Das dürfte auch das kleinere Problem 
sein.
Die Instanz meiner Union ist Bestandteil eines großen Arrays, in dem ich 
nichts mehr verschieben kann. Ein 4.Byte an die Union hängen, geht daher 
nicht.
Nun hat der Tag max. 24h, das sind 5 Bit, weshalb 3 Bit beim Byte für 
die Stunde immer frei bleiben. Die Idee wäre deshalb, diese für die 7 
Wochentage zu nutzen.

Allerdings finde ich aus dem Stehgreif keine Syntax, mit der ich die 
Union so erweitern kann, dass ich die oberen 3 Bit des obersten Bytes 
isoliere. Ein direktes Ansprechen dieser 3 Bit würde aber den Code 
durchaus etwas übersichtlicher gestalten.

Kann da jemand helfen?


Besten Dank im Voraus!

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bit Fields
typedef union
{
    unsigned short long uns24;
    unsigned char v[3];
    struct
    {
        unsigned char sekunde;
        unsigned char minute;
        unsigned char stunde : 5;
        unsigned char tag    : 3;
    };
}S_M_H_Time;
 sollte gehen

Autor: C.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte Bitte für Zahle nur Datentypen daraus verwenden:
#include stdint.h

also bei dir:
uint24_t
uint8_t

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BL schrieb:
> unsigned short long uns24;

short oder long.

Wenn es long ist, hast du schon 4 Byte. dann kannst du auch die strcut 
erweitern.

Wenn es short ist, dann belegt die struct eigentlich 3 Byte.
Wegen des Alignements wird sie aber meist auf 4 BYte aufgeblasen, damit 
sie ohne Problem als Array benutzt werden kann.

Teste das mal mit sizeof(S_M_H_Time)

Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> short oder long.

Nein, Google mal nach uint24_t oder "short long".

Bei manchen Systemen machen 24 Bit Sinn.

Autor: nur malso (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
kleiner Hinweis:

unions zur Typwandlung nutzen ist böse (bzw. kann böse sein ;) )

Aber ich glaube die erfahrung wo das dann richtig knallt muss jeder erst 
mal selber machen. Und ja ich habe die unions früher auch für 
Typwanlungen verwendet weil es soooo praktisch ist.

Autor: Eric B. (beric)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> Bit Fields
>
>
> typedef union
> {
>     unsigned short long uns24;
>     unsigned char v[3];
>     struct
>     {
>         unsigned char sekunde;
>         unsigned char minute;
>         unsigned char stunde : 5;
>         unsigned char tag    : 3;
>     };
> }S_M_H_Time;
> 
> sollte gehen

Und sind dann die 3 bits von "tag" die oberen oder die unteren 3 bits?
Ist v[0] dann gleich "sekunde" oder "stunde/tag"?
Das ist alles implementation defined, also abhängig vom benutzten 
Compiler und Prozessor!

: Bearbeitet durch User
Autor: BL (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Herzlichen Dank erst mal für die schnellen Antworten!

>Teste das mal mit sizeof(S_M_H_Time)

Ergibt 3.

Der Compiler ist XC8, da habe ich dieses "short long" von irgendwoher 
einfach abgeschrieben. Mit dem XC8 arbeite ich erst ein halbes Jahr. 
Vorher hatte ich den CC8e.



>        unsigned char stunde : 5;
>        unsigned char tag    : 3;

Das haut hin, Danke nochmal!


Zur Typumwandlung - ich bin leider kein gelernter C-Experte.
Diese Union-Geschichte fand ich daher zur Typumwandlung eigentlich immer 
ganz elegant. Früher hab ich das mit festen RAM-Addressen gemacht, das 
hatt wirklich seine Tücken.
Wie würde man es denn richtig(er) machen?

Autor: Niklas Gürtler (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
unions in C sind ausschließlich zum Speicher sparen gemacht; erst einen 
Eintrag schreiben und dann einen anderen lesen ist 
implementation-defined behaviour, als gefährlich und unportabel. Siehe 
Serialisierung. Die dort vorgestellte Library kann was du brauchst 
in korrekt und plattformunabhängig.

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
BL schrieb:
> Wie würde man es denn richtig(er) machen?

Maskieren und shiften.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
BL schrieb:

> Zur Typumwandlung - ich bin leider kein gelernter C-Experte.
> Diese Union-Geschichte fand ich daher zur Typumwandlung eigentlich immer
> ganz elegant.

Liest man leider sehr oft und ist bei

bei C: implementation-defined behaviour
bei C++: undefined behaviour

Immer richtig ist ein shift-N-mask-N-or.

> Früher hab ich das mit festen RAM-Addressen gemacht, das
> hatt wirklich seine Tücken.

Das ist dann im Kern dasselbe wie bei den unions: 
implementation-defined.

Das implementation-defined kann man natürlich in seinem Code 
berücksichtigen, etwa in C durch bedingte Compilierung. Ist aber 
trotzdem ein "wackelige" Lösung.

: Bearbeitet durch User
Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitfelder sind nicht portabel (eben weil implementation defined). Das 
sind direkte Hardwarezugriffe (wg. ggf. unterschiedlicher Byte Order) 
aber auch.

Hier sind Bitfelder m.E. sogar völlig ungefährlich.

Wenn ich das richtig verstehe, will der TO den Wochentag sowieso immer 
über den Union-Selektor schreiben und lesen. In dem Fall sind Unions 
sicher die eleganteste und am wenigsten fehlerträchtige Möglichkeit der 
Umsetzung.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Markus F. schrieb:
> Bitfelder sind nicht portabel (eben weil implementation defined).

Bitfelder sind portabel, nur die Zuordnung zu irgendwelchen Bits ist 
implmenetation-defined, sprich etwa bei Serialisierung unbrauchbar.

> Wenn ich das richtig verstehe, will der TO den Wochentag sowieso *immer*
> über den Union-Selektor schreiben und lesen. In dem Fall sind Unions
> sicher die eleganteste und am wenigsten fehlerträchtige Möglichkeit der
> Umsetzung.

Könnte sein, war aber bislang irgendwie nicht zu erkennen aus dem Post 
des TO. Dann ist der Zweck der union aber wirklich nur das Sparen von 
Speicher (gut) und nicht das type-punning (schlecht). Wobei er uns auch 
die Diskriminatorlogik verschwiegen hat ...

: Bearbeitet durch User
Autor: BL (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, trockene Kost.

Ich weiß ja, mir fehlt zum Informatiker etliches. Weshalb ich gerne 
besagte Diskriminatorlogik offenbaren würde, könnte ich irgendwo lernen, 
was das ist.
Dazu aber läßt mir das schnöde Berufsleben derzeit keine/sehr sehr wenig 
Zeit.

Diesen (De-)Serialisierungsarktikel zieh ich mir aber noch mal rein. 
Aber später. Nur, Typumwandlungen per Shiften und Maskieren, kostet 
Programmieraufwand, Flash und Zyklen(was beim aktuellen Projekt aber 
untergeordnet wäre). Deshalb war mir die Union-Geschichte ja so 
sympathisch.

Autor: Niklas G. (erlkoenig) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BL schrieb:
> Nur, Typumwandlungen per Shiften und Maskieren, kostet
> Programmieraufwand

Dafür weniger Aufwand bei der Fehlersuche und Pflege, wenn du mal 
irgendwas an der Umgebung änderst (Compiler-Optionen, -Version, 
-Hersteller, Prozessor, ...). Je später Korrekturen im Projekt 
vorgenommen werden, desto teurer werden sie bekanntlich. Daher am Besten 
gleich richtig machen.

BL schrieb:
> Flash und Zyklen
Gute Compiler optimieren das weg. Probiere es erst aus, bevor du das als 
zu langsam abstempelst.

BL schrieb:
> Deshalb war mir die Union-Geschichte ja so
> sympathisch.
Da hier Speicher-Zugriffe quasi erzwungen werden, kann das sogar 
langsamer sein. unions werden hier für etwas missbraucht für das sie 
nicht da sind, das finden die bestimmt nicht so sympathisch!

BL schrieb:
> Ich weiß ja, mir fehlt zum Informatiker etliches
Dann hör auf die "richtigen" Informatiker und ihre Ratschläge...

: Bearbeitet durch User
Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> bei C: implementation-defined behaviour

Das ist ja auch nicht schlimm. Es gibt in konkreten Projekten halt 
konkrete Implementierungen. Darum muss man sich "erst" beim 
Plattformwechsel oder Compiler-Update kümmern. Mach ein 
Compiletime-Assert dran und fertig.

--> wenn mein (konkreter) Applikations-Code mit Unions deutlich klarer 
wird, nehme ich Unions. Mit CT-Assert. Der Preis ist dann 
gerechtfertigt.

--> wenn mein Treibercode von anderen Leuten (oder von mir) auf 
verschiedenen Plattformen eingesetzt wird, mache ich es portabel. Den 
Preis würden nämlich andere zahlen müssen (und sie werden es nicht tun!)

Man muss die Kirche im Dorf lassen. Wichtig ist nur, zu wissen, was man 
tut (den Preis kennen und es ggf. absichern).

Autor: Vincent H. (vinci)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> Wilhelm M. schrieb:
>> bei C: implementation-defined behaviour
>
> Das ist ja auch nicht schlimm. Es gibt in konkreten Projekten halt
> konkrete Implementierungen. Darum muss man sich "erst" beim
> Plattformwechsel oder Compiler-Update kümmern. Mach ein
> Compiletime-Assert dran und fertig.
>
> --> wenn mein (konkreter) Applikations-Code mit Unions deutlich klarer
> wird, nehme ich Unions. Mit CT-Assert. Der Preis ist dann
> gerechtfertigt.
>
> --> wenn mein Treibercode von anderen Leuten (oder von mir) auf
> verschiedenen Plattformen eingesetzt wird, mache ich es portabel. Den
> Preis würden nämlich andere zahlen müssen (und sie werden es nicht tun!)
>
> Man muss die Kirche im Dorf lassen. Wichtig ist nur, zu wissen, was man
> tut (den Preis kennen und es ggf. absichern).


Kann man das bitte auf der Startseite anschlagen?
Wenn man den Text noch auf "goto" und "malloc" ausweitet, dann kann man 
jeden 3.Thread zu C quasi direkt löschen.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
BL schrieb:
> Oh, trockene Kost.
>
> Ich weiß ja, mir fehlt zum Informatiker etliches. Weshalb ich gerne
> besagte Diskriminatorlogik offenbaren würde, könnte ich irgendwo lernen,
> was das ist.

Dein Code wäre ok, wenn Du bei Objekten dieses Typs immer nur eines der 
union-Elemente verwendest:
typedef union
{
    unsigned short long uns24;
    unsigned char v[3];
    struct
    {
        unsigned char sekunde;
        unsigned char minute;
        unsigned char stunde;
    };
}S_M_H_Time;

...

S_M_H_Time a;
S_M_H_Time b;

...

a.uns24 = ...; // niemals etwas anderes von a verwenden als uns24

b.sekunde = ...; // niemals etwas anderes von b verwenden als sekunde,minute oder stunde


Du sprachst von einem Array, also etwa:
S_M_H_Time array[10];

Wenn Du nun sicherstellen kannst, dass etwa das Element array[0] immer 
nur als array[0].uns24 und etwa array[1].sekunde (s.o.) verwendet wird, 
ist es auch ok.

Wenn aber über das array iterierst, muss Du ja irgendwie entscheiden, 
als was Du das array-Element verwendest: das ist die Diskriminatorlogik 
dann.

(Sorry für den Hinweis: std::variant<> hat diese Logik eingebaut)

> Dazu aber läßt mir das schnöde Berufsleben derzeit keine/sehr sehr wenig
> Zeit.

Das würde ich versuchen zu ändern ;-)

Autor: Claus M. (energy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Recht erschreckend, dass man mit so wenig Wissen tatsächlich Kunden 
hat... Gut, dass man SW nicht sehen kann...

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erweiterte Frage:
union {
 uint8_t u8[2];
 uint16_t u16;
} x = { 1, 2 };
memmove(&x.u16, &x, 2);
return x.u16;
Undefined oder nicht?

: Bearbeitet durch User
Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko L. schrieb:
> Undefined oder nicht?

Undefined in C++, Implementation defined in C, denn das Ergebnis in u16 
hängt von der Endianness der Plattform ab.

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woher kommt das undefined?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Heiko L. schrieb:
> Woher kommt das undefined?

Weil in C++ die DT in der union auch UDT sein können. Diese haben im 
allgemeinen ctor'en bzw. dtor'en. Beim Wechsel des aktiven Elementes in 
der union müssten dann eigentlich die ctor'en bzw. dtor'en aufgerufen 
werden. Das findet lt. Standard aber nicht statt. Insofern würde der 
Wechsel des aktiven Elementes zu einem uninitialisierten ELement führen. 
Und das ist UB.

: Bearbeitet durch User
Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Heiko L. schrieb:
>> Woher kommt das undefined?
>
> Weil in C++ die DT in der union auch UDT sein können. Diese haben im
> allgemeinen ctor'en bzw. dtor'en. Beim Wechsel des aktiven Elementes in
> der union müssten dann eigentlich die ctor'en bzw. dtor'en aufgerufen
> werden. Das findet lt. Standard aber nicht statt. Insofern würde der
> Wechsel des aktiven Elementes zu einem uninitialisierten ELement führen.
> Und das ist UB.

Das trifft hier aber gar nicht zu:

If members of a union *are classes with user-defined constructors and 
destructors*, to switch the active member, explicit destructor and 
placement new are generally needed

: Bearbeitet durch User
Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Heiko L. schrieb:
>> Woher kommt das undefined?
>
> Weil in C++ die DT in der union auch UDT sein können. Diese haben im
> allgemeinen ctor'en bzw. dtor'en. Beim Wechsel des aktiven Elementes in
> der union müssten dann eigentlich die ctor'en bzw. dtor'en aufgerufen
> werden. Das findet lt. Standard aber nicht statt. Insofern würde der
> Wechsel des aktiven Elementes zu einem uninitialisierten ELement führen.
> Und das ist UB.

Ich habe jetzt nicht im Standard nachgelesen, aber laut 
http://en.cppreference.com/w/cpp/string/byte/memmove ist memmove OK, 
wenn der DT TriviallyCopyable ist. Ich würde memmove hier nicht nutzen, 
ohne vorher sicherzugehen, dass strict aliasing nicht verletzt wird.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
mh schrieb:
> Wilhelm M. schrieb:
>> Heiko L. schrieb:
>>> Woher kommt das undefined?
>>
>> Weil in C++ die DT in der union auch UDT sein können. Diese haben im
>> allgemeinen ctor'en bzw. dtor'en. Beim Wechsel des aktiven Elementes in
>> der union müssten dann eigentlich die ctor'en bzw. dtor'en aufgerufen
>> werden. Das findet lt. Standard aber nicht statt. Insofern würde der
>> Wechsel des aktiven Elementes zu einem uninitialisierten ELement führen.
>> Und das ist UB.
>
> Ich habe jetzt nicht im Standard nachgelesen, aber laut
> http://en.cppreference.com/w/cpp/string/byte/memmove ist memmove OK,
> wenn der DT TriviallyCopyable ist. Ich würde memmove hier nicht nutzen,
> ohne vorher sicherzugehen, dass strict aliasing nicht verletzt wird.

Da memmove nicht explizit genannt wird, um das active member auch bei 
trivially copyable objekten genannt wird, würde ich es als UB werten: Du 
liest von einem nicht active member, was keine common initail sequence 
mit dem active member hat.

Autor: W.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BL schrieb:
> Ich habe eine Union für die Uhrzeit gemacht.
>....
> In die wird ein RTCC reingelesen und das funktioniert soweit auch alles.


Soweit...

Ich halte deine gesamte Vorgehensweise für falsch. Was willst du 
eigentlich mit solchem Union machen? Du hast nur dran gedacht, den 
Inhalt deines RTC irgendwohin zu verfrachten - aber nicht daran, daß 
diese Daten ja anschließend verwendet werden sollen. Und das geht mit 
solchem Union eben miserabel bis hin zur Bauchlandung.

Du hättest es von Anfang an anders machen sollen: Ab irgend einem 
sinnvollen Datum, z.B. 1.1.2000 oder 1.1.1970 die Zeit in Sekunden 
zählen und dies in einem long speichern (reicht für etwa +/-68 Jahre) 
oder in einem int64 (reicht fast ewig).

Mit deinen vorhandenen 24 Bit kannst du nur die 
Tage,Stunden,Minuten,Sekunden zählen. Das reicht nicht mal für ein Jahr 
(24 Bit macht 16 Mio, brauchen würdest du ca. 32 Mio), aber für ne Woche 
reicht es allemal.

Also Zeit = ((Wochentag * 24 + Stunden) * 60 + Minuten) * 60 + Sekunden;

Das BLÖDE daran ist, daß ein Integer von 24 Bit sowas von unüblich 
ist, daß sich einem der Magen umdreht. Also bleibt dir bloß
struct Zeit 
{ byte hoechstes;
  byte mittleres;
  byte kleinstes;
}
So etwa.

W.S.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> mh schrieb:
>> Wilhelm M. schrieb:
>>> Heiko L. schrieb:
>>>> Woher kommt das undefined?
>>>
>>> Weil in C++ die DT in der union auch UDT sein können. Diese haben im
>>> allgemeinen ctor'en bzw. dtor'en. Beim Wechsel des aktiven Elementes in
>>> der union müssten dann eigentlich die ctor'en bzw. dtor'en aufgerufen
>>> werden. Das findet lt. Standard aber nicht statt. Insofern würde der
>>> Wechsel des aktiven Elementes zu einem uninitialisierten ELement führen.
>>> Und das ist UB.
>>
>> Ich habe jetzt nicht im Standard nachgelesen, aber laut
>> http://en.cppreference.com/w/cpp/string/byte/memmove ist memmove OK,
>> wenn der DT TriviallyCopyable ist. Ich würde memmove hier nicht nutzen,
>> ohne vorher sicherzugehen, dass strict aliasing nicht verletzt wird.
>
> Da memmove nicht explizit genannt wird, um das active member auch bei
> trivially copyable objekten genannt wird, würde ich es als UB werten: Du
> liest von einem nicht active member, was keine common initail sequence
> mit dem active member hat.

Sollte heissen:
Da memmove nicht explizit genannt wird, um das active member auch bei
trivially copyable objekten zu wechseln ...

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Da memmove nicht explizit genannt wird, um das active member auch bei
> trivially copyable objekten genannt wird, würde ich es als UB werten: Du
> liest von einem nicht active member, was keine common initail sequence
> mit dem active member hat.

Aus dem C11 Standard zu memmove:
The memmove function copies n characters from the object pointed to by s2 into the
object pointed to by s1. Copying takes place as if the n characters from the object
pointed to by s2 are first copied into a temporary array of n characters that does not
overlap the objects pointed to by s1 and s2, and then the n characters from the
temporary array are copied into the object pointed to by s1.
Das Ergebnis von memmove ist also "as if" erst aus der Quelle in einen 
Zwischenspeicher kopiert wird und dann aus dem Zwischenspeicher ins 
Ziel. Es wird also nicht auf beide member der union zugeriffen.

Für mich ist es grad zu spät, um mich genauer mit den Lifetime Regeln 
von unions im C++ Standard auseinanderzusetzen...

Hast du vllt. Zeit und Interesse daran herauszufinden, was clangs 
UB-sanitizer dazu sagt? ;-)

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> Hast du vllt. Zeit und Interesse daran herauszufinden, was clangs
> UB-sanitizer dazu sagt? ;-)

Also ich habe es gerade auprobiert und bin damit auch echt 
durchgekommen. Oder muss man noch mehr als "-fsanitize=undefined" 
angeben? Bin die Liste durchgegangen, es klang aber nichts sonderlich 
passend.

Autor: Karl (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Was ist eigentlich daraus geworden, das ein char  immer aliasen darf und 
deshalb eine Union auch dazu verwendet werden darf von Typ x nach char 
Array und zurück zu wandeln?
GCC meckert diesen Fall auch bei strict aliasing Rules nicht an.

Autor: MaWin O. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:
> deshalb eine Union auch dazu verwendet werden darf von Typ x nach char
> Array und zurück zu wandeln?

Diese Regel gab es im Standard nie.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Markus F. schrieb:
>> Bitfelder sind nicht portabel (eben weil implementation defined).
>
> Bitfelder sind portabel, nur die Zuordnung zu irgendwelchen Bits ist
> implmenetation-defined, sprich etwa bei Serialisierung unbrauchbar.

Ja, genau. Bitfelder sind portabel, solange man sie so nutzt, wie es 
vorgesehen ist. Das gleiche gilt für unions. Das hier ist aber 
Missbrauch sowohl von Bitfeldern, als auch von Unions.

BL schrieb:
> Diesen (De-)Serialisierungsarktikel zieh ich mir aber noch mal rein.
> Aber später. Nur, Typumwandlungen per Shiften und Maskieren, kostet
> Programmieraufwand, Flash und Zyklen(was beim aktuellen Projekt aber
> untergeordnet wäre). Deshalb war mir die Union-Geschichte ja so
> sympathisch.

Und du meinst, bei der Union-Variante extrahiert der Prozessor die Bits 
per Magie da raus? Der muss natürlich die gleichen Operationen machen, 
nur sind sie dann versteckt.

Achim S. schrieb:
> Wilhelm M. schrieb:
>> bei C: implementation-defined behaviour
>
> Das ist ja auch nicht schlimm. Es gibt in konkreten Projekten halt
> konkrete Implementierungen. Darum muss man sich "erst" beim
> Plattformwechsel oder Compiler-Update kümmern. Mach ein
> Compiletime-Assert dran und fertig.

Das sehe ich etwas anders. Wenn man sich dann irgendwann entscheidet, 
das Programm zu portieren, hat man Tausende von unportablen Konstrukten 
im Programm, und die Portierung ist ein riesen Aufwand.
Wenn man dagegen gleich etwas darauf achtet, die Sachen portabel zu 
halten, kostet das meistens kaum Zusatzaufwand, und das Portieren ist 
nachher erheblich einfacher.

Autor: Oliver S. (oliverso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Das sehe ich etwas anders. Wenn man sich dann irgendwann entscheidet,
> das Programm zu portieren, hat man Tausende von unportablen Konstrukten
> im Programm, und die Portierung ist ein riesen Aufwand.

Die Chance, daß das auf einer anderen Architektur oder mit einem anderen 
Compiler auch funktioniert, ist allerdings nicht so ganz klein.

Ich sehe den generellen Schwachpunkt der ganzen Geschichte eher hier:

BL schrieb:
> Die Instanz meiner Union ist Bestandteil eines großen Arrays, in dem ich
> nichts mehr verschieben kann. Ein 4.Byte an die Union hängen, geht daher
> nicht.

Das fliegt denen mit Sicherheit noch mehrfach um die Ohren, vor allem, 
wenn „der Kunde“ sein Anforderungen noch häufiger ändert.

Oliver

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Und du meinst, bei der Union-Variante extrahiert der Prozessor die Bits
> per Magie da raus? Der muss natürlich die gleichen Operationen machen,
> nur sind sie dann versteckt.

Ich finde es schon komisch, dass der C++-Way-to-do-it ist, eine 
C-Funktion zu verwenden...

Autor: Niklas Gürtler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko L. schrieb:
> Ich finde es schon komisch, dass der C++-Way-to-do-it ist, eine
> C-Funktion zu verwenden...

Die meisten C Bestandteile sind auch in C++ sehr wichtig. Für Funktionen 
und arithmetische Berechnungen hat C++ auch keinen Ersatz, nur 
Erweiterungen.

Beitrag #5426119 wurde vom Autor gelöscht.
Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ma W. schrieb:
> Diese Regel gab es im Standard nie.

Ich meine schon. Schau bei Gelegenheit nach.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Karl schrieb:
> Ma W. schrieb:
>> Diese Regel gab es im Standard nie.
>
> Ich meine schon. Schau bei Gelegenheit nach.

Du meinst wahrscheinlich, dass char* zu jedem anderen T* als alias 
betrachtet wird und man deswegen die Objektrepräsentation anderer Typen 
byteweise durch einen char* lesen darf. So (frei übersetzt) steht es im 
Standard (die Umkehrung gilt i.d.R. nicht).

: Bearbeitet durch User
Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Du meinst wahrscheinlich, dass char* zu jedem anderen T* als alias
> betrachtet wird und man deswegen die Objektrepräsentation anderer Typen
> byteweise durch einen char* lesen darf. So (frei übersetzt) steht es im
> Standard (die Umkehrung gilt i.d.R. nicht).

Keine Ahnung. Meine ich das?
Folgender Auszug lässt mich anders denken.
If a value is copied into an object having no declared type using
memcpy or memmove, or is copied as an array of character type, then the effective type
of the modified object for that access and for subsequent accesses that do not modify the
value is the effective type of the object from which the value is copied, if it has one. For
all other accesses to an object having no declared type, the effective type of the object is
simply the type of the lvalue used for the access.


7 An object shall have its stored value accessed only by an lvalue expression that has one of
the following types:76)
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the
object,
— a type that is the signed or unsigned type corresponding to a qualified version of the
effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its
members (including, recursively,amember of a subaggregate or contained union), or
— a character type 

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.