Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: C++ (alle ISO-Standards) ::  union -> struct inside  
Gehen Sie zu Seite 1, 2  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
breakpoint
Mitglied

Benutzerprofil
Anmeldungsdatum: 09.01.2017
Beiträge: 1
Beitrag breakpoint Mitglied 20:19:50 10.01.2017   Titel:   union -> struct inside            Zitieren

Hi,
ich habe folgenden Code:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
union myColor{
struct{ //anonymer Struct
    unsigned char a,b,g,r; //falsch herum ist absicht!
};
unsigned int rgba;
};
 
int main(int argc, char** argv){
    myColor color;
    color.rgba = 0xFFC080AA;
    std::cout << +color.r << " " << +color.g << " " << +color.b << " " +color.a << std::endl; //+ bedeutet: als Zahl interpretieren
 
}



Wie weiß ich, dass im struct die verschiedenen a,b,g,r sind?.
Ich weiß, dass das rückwärts wegen dem Big Endian ist.. aber wie kann er es in einem struct verpackt erkennen und zuordnen? So viel Intelligenz traue ich dem Compiler nicht zu ;)

Vielen Dank für Antworten :)
manni66
Unregistrierter




Beitrag manni66 Unregistrierter 20:40:47 10.01.2017   Titel:              Zitieren

Warum nimmst du an, dass hier Compilerintelligenz nötig wäre?
Das Ganze ist undefiniertes Verhalten. Wenn die Bytes des unsigned richtig "unter" den Bytes der char liegen passt es halt.
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23742
Beitrag hustbaer Mitglied 23:12:34 10.01.2017   Titel:   Re: union -> struct inside            Zitieren

@manni66
Was ist hier deiner Meinung nach UB?
Strict-Aliasing greift mMn. nicht weil Ausnahme für unsigned char. IB ist es natürlich, weil der Standard nicht festlegt wie die Bits in einem unsigned int angeordnet zu sein haben. Aber IB ist eben nicht UB.

breakpoint schrieb:
aber wie kann er es in einem struct verpackt erkennen und zuordnen? So viel Intelligenz traue ich dem Compiler nicht zu ;)

Du traust dem Compiler nicht zu zu wissen dass er Variablen in POD-Structs in der Reihenfolge in den Speicher legt wie sie im Source-File stehen? Oder dass er bei Unions für jeden "Teil" der Union an der selben Adresse anfängt? Oder dass er bei Integers die grösser als ein Byte sind die native Byte-Order verwendet? Was traust du dem Compiler noch alles nicht zu, dass er 1 + 1 nicht zusammenzählen kann?

Anders gesagt: der Compiler muss hier nix über die Byte-Order der Maschine wissen. Der Code wird sich auch hübsch reproduzierbar auf Little-Endian anders verhalten als auf Big-Endian. Davon abgesehen weiss der Compiler üblicherweise sehr genau was "seine" CPU so macht.
Guggsdu: https://godbolt.org/g/u0cZan
Sieh dir den Code an der für diese Funktionen generiert. Und dann überleg dir nochmal was du dem Compiler zutraust und was nicht. :)
Ich persönlich finde das schon recht beeindruckend. Vor allem das letzte Beispiel (quux).

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at
manni66
Unregistrierter




Beitrag manni66 Unregistrierter 23:45:18 10.01.2017   Titel:   Re: union -> struct inside            Zitieren

hustbaer schrieb:
@manni66
Was ist hier deiner Meinung nach UB?

Der lesende Zugriff auf ein Member, dem nicht vorher ein Wert zugewiesen wurde.
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23742
Beitrag hustbaer Mitglied 00:34:49 11.01.2017   Titel:              Zitieren

* Der Speicher wurde initialisiert.
* Der Zugriff erfolgt über nen unsigned char.
Wäre es ein anderer Typ wie z.B. unsigned short wäre die Sache klar und du hättest natürlich Recht. So kann ich hier aber kein Problem sehen.

Lesen per *reinterpret_cast<unsigned char*>(&color)[0] wäre definitiv OK. Ich denke dann sollte auch Lesen per color.a OK sein.

Was sagen die Standard-Gurus? :confused:

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at


Zuletzt bearbeitet von hustbaer am 00:36:52 11.01.2017, insgesamt 2-mal bearbeitet
nonpro
Unregistrierter




Beitrag nonpro Unregistrierter 03:01:43 11.01.2017   Titel:              Zitieren

hustbaer schrieb:
* Der Speicher wurde initialisiert.
* Der Zugriff erfolgt über nen unsigned char.

Es ist in obigem Code nicht sichergestellt, dass die Größe des structs gleich der Größe eines unsigned ints ist. Das klappt heute und der nächste Compiler meint vielleicht, Padding-Bytes einschieben zu müssen.
Klar, einfach die Member auf 1 Byte ausrichten lasen, dann bliebe noch das Schreiben eines und Lesen des anderen Werts...

Campers Meinung würde mich zwar auch interessieren, aber mit mit den passend definierten Masken zum Lesen der einzelnen Werte ist es doch auch nicht umständlicher und garantiert standardkonform, sodass der Code nicht wirklich nützlich ist und noch Fallstricke bereitstellt.
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23742
Beitrag hustbaer Mitglied 10:24:27 11.01.2017   Titel:              Zitieren

OK. Wenn unsigned int z.B. nur 16 Bit wäre, dann wäre es UB. Wohl wahr.
Wenn sizeof(unsigned int) >= 4, dann sehe ich hier kein UB. Es ist also sozusagen IB ob es UB ist oder nicht :D

nonpro schrieb:
(...) mit den passend definierten Masken zum Lesen der einzelnen Werte ist es doch auch nicht umständlicher und garantiert standardkonform, sodass der Code nicht wirklich nützlich ist und noch Fallstricke bereitstellt.

Klar, kein Einwand.

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at
DirkB
Mitglied

Benutzerprofil
Anmeldungsdatum: 24.01.2016
Beiträge: 906
Beitrag DirkB Mitglied 10:35:45 11.01.2017   Titel:              Zitieren

Wenn sizeof(unsigned int) > 4 ist (das = ist weg), dann funktioniert die union bei Big-Endian-Systemen nicht mehr.

nonpro schrieb:
..., aber mit mit den passend definierten Masken zum Lesen der einzelnen Werte ist es doch auch nicht umständlicher und garantiert standardkonform, sodass der Code nicht wirklich nützlich ist und noch Fallstricke bereitstellt.
Und der der Compiler macht daraus auch keinen langsameren Code.


Zuletzt bearbeitet von DirkB am 10:41:06 11.01.2017, insgesamt 1-mal bearbeitet
manni66
Unregistrierter




Beitrag manni66 Unregistrierter 10:46:04 11.01.2017   Titel:              Zitieren

Leider ist der Standard erstaunlich vage bei der Definition von Unions.
Aber
Standard schrieb:

9.5 Unions [class.union]

In a union, at most one of the non-static data members can be active at any time, that is, the value of at
most one of the non-static data members can be stored in a union at any time.
[Note:
One special guarantee
is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout
structs that share a common initial sequence (9.2), and if an object of this standard-layout union type
contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of
standard-layout struct members; see 9.2.
— end note]

Es gibt also genau ein aktives Element, und auf die anderen darf nur in Ausnahmefällen zugegriffen werden.

Siehe ebenfalls http://en.cppreference.com/w/cpp/language/union:
Zitat:

...
it's undefined behavior to read from the member of the union that wasn't most recently written.
SeppJ
Global Moderator

Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 28191
Beitrag SeppJ Global Moderator 11:14:56 11.01.2017   Titel:              Zitieren

Ganz so einfach ist das nicht, manni66. hustbaer bezieht sich gerade auf diese Ausnahmefälle. Leider ist der Standard in dieser Hinsicht ziemlich schwer verständlich/ungeschickt formuliert. Die Intention des Standards ist vermutlich, dass es erlaubt sein sollte, denn in C ist es explizit erlaubt und man wollte beim Standard möglichst erreichen, dass C++ in Hinsicht des Speicherlayouts trivialer Objekte möglichst kompatibel zu C ist. Mit den ganzen Verklausulierungen des Standards ist am Ende aber meiner Einschätzung nach etwas heraus gekommen, das auf undefiniertes Verhalten in diesem Fall hinaus läuft.

Man kann sich praktisch aber darauf herausreden, dass der GCC (und vermutlich alle bekannten Compiler) ganz explizit sagt, dass dies funktionieren wird.

_________________
Korrekte Rechtschreibung und Grammatik sind das sprachliche Äquivalent zu einer Dusche und gepflegter Kleidung.


Zuletzt bearbeitet von SeppJ am 11:15:51 11.01.2017, insgesamt 1-mal bearbeitet
C++ Forum :: C++ (alle ISO-Standards) ::  union -> struct inside  
Gehen Sie zu Seite 1, 2  Weiter
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.