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!
Bit Fields
1 | typedef union |
2 | {
|
3 | unsigned short long uns24; |
4 | unsigned char v[3]; |
5 | struct
|
6 | {
|
7 | unsigned char sekunde; |
8 | unsigned char minute; |
9 | unsigned char stunde : 5; |
10 | unsigned char tag : 3; |
11 | };
|
12 | }S_M_H_Time; |
sollte gehen
Bitte Bitte für Zahle nur Datentypen daraus verwenden: #include stdint.h also bei dir: uint24_t uint8_t
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)
Dirk B. schrieb: > short oder long. Nein, Google mal nach uint24_t oder "short long". Bei manchen Systemen machen 24 Bit Sinn.
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.
Dirk B. schrieb: > Bit Fields > >
1 | > typedef union |
2 | > { |
3 | > unsigned short long uns24; |
4 | > unsigned char v[3]; |
5 | > struct |
6 | > { |
7 | > unsigned char sekunde; |
8 | > unsigned char minute; |
9 | > unsigned char stunde : 5; |
10 | > unsigned char tag : 3; |
11 | > }; |
12 | > }S_M_H_Time; |
13 | >
|
> 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
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?
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.
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
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.
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
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.
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
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).
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.
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:
1 | typedef union |
2 | {
|
3 | unsigned short long uns24; |
4 | unsigned char v[3]; |
5 | struct
|
6 | {
|
7 | unsigned char sekunde; |
8 | unsigned char minute; |
9 | unsigned char stunde; |
10 | };
|
11 | }S_M_H_Time; |
12 | |
13 | ...
|
14 | |
15 | S_M_H_Time a; |
16 | S_M_H_Time b; |
17 | |
18 | ...
|
19 | |
20 | a.uns24 = ...; // niemals etwas anderes von a verwenden als uns24 |
21 | |
22 | b.sekunde = ...; // niemals etwas anderes von b verwenden als sekunde,minute oder stunde |
Du sprachst von einem Array, also etwa:
1 | 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 ;-)
Recht erschreckend, dass man mit so wenig Wissen tatsächlich Kunden hat... Gut, dass man SW nicht sehen kann...
Erweiterte Frage:
1 | union { |
2 | uint8_t u8[2]; |
3 | uint16_t u16; |
4 | } x = { 1, 2 }; |
5 | memmove(&x.u16, &x, 2); |
6 | return x.u16; |
Undefined oder nicht?
:
Bearbeitet durch User
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.
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
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
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.
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.
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ß
1 | struct Zeit |
2 | { byte hoechstes; |
3 | byte mittleres; |
4 | byte kleinstes; |
5 | }
|
So etwa. W.S.
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 ...
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:
1 | The memmove function copies n characters from the object pointed to by s2 into the |
2 | object pointed to by s1. Copying takes place as if the n characters from the object |
3 | pointed to by s2 are first copied into a temporary array of n characters that does not |
4 | overlap the objects pointed to by s1 and s2, and then the n characters from the |
5 | 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? ;-)
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.
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.
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.
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.
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
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...
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 von einem Moderator gelöscht.
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
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.
1 | If a value is copied into an object having no declared type using |
2 | memcpy or memmove, or is copied as an array of character type, then the effective type |
3 | of the modified object for that access and for subsequent accesses that do not modify the |
4 | value is the effective type of the object from which the value is copied, if it has one. For |
5 | all other accesses to an object having no declared type, the effective type of the object is |
6 | simply the type of the lvalue used for the access. |
7 | |
8 | |
9 | 7 An object shall have its stored value accessed only by an lvalue expression that has one of |
10 | the following types:76) |
11 | — a type compatible with the effective type of the object, |
12 | — a qualified version of a type compatible with the effective type of the object, |
13 | — a type that is the signed or unsigned type corresponding to the effective type of the |
14 | object, |
15 | — a type that is the signed or unsigned type corresponding to a qualified version of the |
16 | effective type of the object, |
17 | — an aggregate or union type that includes one of the aforementioned types among its |
18 | members (including, recursively,amember of a subaggregate or contained union), or |
19 | — a character type |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.