Unions oder doch Bit-Shift und Bit-Operationen



  • @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    edit: Oh, super, jetzt wirst du sagen, dass dein byte ein unsigned char ist und das deswegen nicht aliased. Als ob das Absicht gewesen wäre...

    Naja nachdem da steht

    using byte = char unsigned;  // kein std::uint8_t ... aliasing ...
    

    ...war es vermutlich Absicht 🙂



  • @hustbaer Wenigstens einer der mich versteht *schnief* *Taschentuchholengeh*

    @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Naja, noch mal Glück gehabt

    Glück!?

    (zufällig getroffenen?)

    wtf? Denkst Du ich würfle!?

    @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Als ob das Absicht gewesen wäre.

    *rolleyes* (der smiley wäre nicht aussagekräftig genug gewesen)

    Und ich habe auch eingangs schon gesagt

    @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Immerhin geht es "nur" um 16-bit register

    char unsigned 8 bit, 16 = 2 x 8. Passt wie Faust auf Auge.

    Was soll daran schlechtes Vorbild sein @SeppJ? Das ist doch genau das worum es geht, zu wissen was geht und was nicht geht.



  • @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Oh, super, jetzt wirst du sagen, dass dein byte ein unsigned char ist und das deswegen nicht aliased. Als ob das Absicht gewesen wäre. Naja, noch mal Glück gehabt, aber trotzdem ein sehr schlechtes Vorbild, weil das nur unter diesen genau speziell gewählten (zufällig getroffenen?) Umständen ausnahmsweise erlaubt ist.

    Ne, ernsthaft. Du darfst ruhig von Deinem hohen Ross ab und zu runterkommen und brauchst nicht jedem anderem per se unterstellen er wisse nicht was er tue. Es nervt und ist verletzend. Und das obwohl ich das sogar extra noch als Kommentar hingeschrieben habe, Du Horst! (sorry).

    @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    dass dein byte ein unsigned char ist und das deswegen nicht aliased.

    Doch, er aliased. Aber er darf auch. Krümelkacken kann ich auch.

    </rant>



  • @TGGC sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    @Finnegan
    Wenn man es nicht manuell machen soll, gibts also eine automatisierte Lösung? Diese ist im Compiler eingebaut und die nutze ich, die ist tausendfach getestet. Wer meint, kann das gern neu erfinden und damit seine Zeit verschwenden mit Implementation und Bugsuche. Ich empfehle es niemandem.

    Mein Argument war nicht für oder gegen eine spezielle Lösung, sondern dass dein Einwand mit den "tausenden Bitshifts" nicht zutreffen muss (was ich unter "manuell" verstehe), da man sowas in C++ sehr schön in einer Klasse zentralisieren kann. Das würde ich übrigens auch für die Union-Lösung bevorzugen, sonst hat man statt der "tausenden Bitshifts" nachher tausende, nicht-standardkonforme Union-Zugriffe. Wenn die irgendwann mal nicht mehr so funktionieren sollten, wie erwartet - oder aber auch wenn es mal eine bessere und standardkonforme Lösung dafür geben sollte, lässt sich das so wesentlich besser warten. Ich halte solche Abstraktionen für etwas völlig natürliches und alles andere als "Zeitverschwendung", wenn sie gut durchdacht sind. Die sind für mich ein wichtiges Werkzeug, dem ständigen Sog wachsender Kompexität in Softwareprojekten etwas entgegenzusetzen.

    @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    class reg16_t
    {
    	word value;
    
    public:
    	byte &high  = reinterpret_cast<byte*>(&value)[1];  // wird wohl immer
    	byte &low   = reinterpret_cast<byte*>(&value)[0];  // gratis sein.
    

    So ganz "gratis" ist das nicht, da es zwei zusätzliche Daten-Member sind, welche eigentlich nur triviale Infomation enthalten. Ich fände es besser, diese bei Bedarf "on-the-fly" zu berechnen, was dann wohl letztendlich im generierten Code ausschliesslich in Registern bzw. mithilfe von Address-Offsets umgesetzt wird. Das hat den Vorteil, dass ein reg16_t Im Speicher exakt wie ein word aussieht und sogar TriviallyCopyable wäre, so dass beide Typen via memcpy ineinander kopiert werden könnten (die Referenz-Member erfordern eigene Copy/Move-/Assignment-Operatoren, welche die TriviallyCopyable-Eigenschaft verhindern). Auch sind die Referenz-Member nicht unbedingt cache-freundlich, wenn man es mal mit einem größeren reg16_t-Array zu tun hat. Eine "leichtgewichtige Abstraktion" ist das also in dieser Form meines Erachtens nicht 😉

    @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Sich über Unions beschweren, aber dann gröbste strict aliasing Verletzungen begehen. Super.
    ff.

    Vielleicht ist es hilfreicher, den Diskurs etwas ruhiger zu halten. Man macht es sich unnötig schwerer, Leute zu überzeugen, wenn man sie dabei vor den Kopf stößt. Ich bin eigentlich auch jemand, der erstmal die standardkonforme Variante bevorzugt, würde mich aber von Argumenten wie Performance und weitreichender Compiler-Unterstützung durchaus überzeugen lassen. Das Ihr-habt-keine-Ahnung-Signal, dass hier jedoch zwischen den Zeilen transportiert wird, erzeugt allerdings auch bei mir eine gewisse Trotzreaktion. Mir wäre es lieber wir würden hier gemeinsam versuchen, die beste Lösung zu finden, anstatt alle nur möglichst gut aussehen zu wollen.



  • @Finnegan sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    So ganz "gratis" ist das nicht, da es zwei zusätzliche Daten-Member sind, welche eigentlich nur triviale Infomation enthalten.

    Ich meinte damit, daß Du die im Kompilat nicht finden wirst.

    @Finnegan sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    TriviallyCopyable

    Ist ein Argument, wenn mans braucht? Aber das wäre ja auch einfach zu ändern. Referenzen rauswerfen und stattdessen 4 Funktionen schreiben.



  • @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    @Finnegan sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    So ganz "gratis" ist das nicht, da es zwei zusätzliche Daten-Member sind, welche eigentlich nur triviale Infomation enthalten.

    Ich meinte damit, daß Du die im Kompilat nicht finden wirst.

    Ich denke schon. Im Maschinencode sehen die Referenzen wahrscheinlich wie zwei Pointer-Member aus, die auch in den Speicher geschreiben werden, wenn das reg16_t-Objekt nicht so kurzlebig ist, dass sich das alles in ein paar reine Register-Operationen optimieren lässt.

    @Finnegan sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    TriviallyCopyable

    Ist ein Argument, wenn mans braucht? Aber das wäre ja auch einfach zu ändern. Referenzen rauswerfen und stattdessen 4 Funktionen schreiben.

    Das ist vielleicht nicht unbedingt notwendig, aber dennoch gerade für das Anwendungsgebiet in einem Emulator eine sehr praktische Eigenschaft. Später den kompletten Zustand eines simulierten Computers einfach so via memcpy kopieren oder auch im Block in eine Datei schreiben zu können, empfinde ich als lohnenswertes Designziel - zumal es hier kein übermäßiger Mehraufwand ist.



  • @Finnegan sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Ich denke schon. Im Maschinencode sehen die Referenzen wahrscheinlich wie zwei Pointer-Member aus, die auch in den Speicher geschreiben werden, wenn das reg16_t-Objekt nicht so kurzlebig ist, dass sich das alles in ein paar reine Register-Operationen optimieren lässt.

    Das glaube und hoffe ich eben nicht. Ich gehe eher davon aus daß Zugriffe auf diese Member direkt in Zugriffe auf value übersetzt werden. Wäre sonst ja auch ziemlich Banane. Das meinte ich mit "wird wohl immer gratis sein".

    @Finnegan sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Das ist vielleicht nicht unbedingt notwendig, aber dennoch gerade für das Anwendungsgebiet in einem Emulator eine sehr praktische Eigenschaft. Später den kompletten Zustand eines simulierten Computers einfach so via memcpy kopieren oder auch im Block in eine Datei schreiben zu können, empfinde ich als lohnenswertes Designziel - zumal es hier kein übermäßiger Mehraufwand ist.

    Ein static_cast<> von reg16_t nach word und man kann das tun ... aber wie gesagt, drop die Referenzen, schreib stattdessen vier Funktionen (die im Kompilat aufs selbe rauslaufen sollten) und Deine Wünsche sind erfüllt. Andreaseits, um den Zugriff auf diese "Subregister" ging es ja garnicht vorrangig sondern um das setzen von Flags in einem Byte. Und mein Punkt war daß man dafür kein unportables Bitset braucht sondern nur zwei Funktionen.


  • Mod

    @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    char unsigned 8 bit, 16 = 2 x 8. Passt wie Faust auf Auge.

    Was soll daran schlechtes Vorbild sein @SeppJ? Das ist doch genau das worum es geht, zu wissen was geht und was nicht geht.

    Dass das nur in diesem einen ganz speziellen Fall von 2x8Bit passt, wegen obskurer Sonderregeln, dass chars das ausnahmsweise dürfen? Der Lösungsweg wird beim kleinsten Anzeichen von Anforderungsänderung explodieren. Und zwar nicht auf die theoretische Art, wie dass der Union-Trick streng genommen nicht funktionieren könnte (aber funktionieren wird), sondern auf die böse Art, wo in der Compileranleitung explizit mit Beispiel davor gewarnt wird, dass das nicht funktionieren wird.



  • @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    obskurer Sonderregeln

    Obskure Sonderregeln? Sorry, aber das ist schon immer so, war immer so und wird immer so sein daß chars, unsigned chars (und jetzt auch std::byte) aliasen dürfen. Ich würde eher im Hinblick auf Compilererweiterungen über "obskur" reden.

    @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Der Lösungsweg wird beim kleinsten Anzeichen von Anforderungsänderung explodieren.

    Ängerung der Anforderungen die es bei der Simulation eines 16 bit Prozessors nie nicht geben wird. (Hat man plötzlich eine 32- oder 64-bit CPU ist wohl die andere Registerbreite das was einem am wenigsten Kopfzerbrechen bereiten sollte.)

    @SeppJ
    @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    aber wie gesagt, drop die Referenzen, schreib stattdessen vier Funktionen (die im Kompilat aufs selbe rauslaufen sollten) und Deine Wünsche sind erfüllt.

    @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    um den Zugriff auf diese "Subregister" ging es ja garnicht vorrangig sondern um das setzen von Flags in einem Byte.


  • Mod

    Letztlich hast du aber eine direkt in die Sprache eingebaute Lösung, die praktisch immer funktioniert, und allgemein auf alles anwendbar ist, durch einen komplizierteren Eigenbau ersetzt, der in genau einem bestimmten Sonderszenario funktionieren wird. Und dieses Sonderszenario ist eines, wo die Unionlösung aus den gleichen Gründen (dass char-Zugriffe vom Optimierer potentiell als aliased angesehen werden) in jedem praktischen Szenario funktionieren wird. Wenn das kein schlechtes Vorbild ist, was dann?



  • @SeppJ Ich habe Dir doch schon gesagt daß sowas gerne im Compiler/IDE-Forum diskutiert werden kann. Vom Standard ist es nicht gedeckt. Mich verwundert auch ein wenig daß Du da offenbar Deine persönliche Meinung über Deine Aufgaben als Moderator stellst. Aber sei's drum.



  • C++ braucht dringend einen Standard, der definiert, welche Regeln man aus dem ersten Standard einhalten sollte! Und bei diesem neuen Standard bitte nicht den selben Fehler machen und direkt einen weiteren Standard definieren, der den zweiten Standard überwacht!


  • Mod

    @Swordfish sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    @SeppJ Ich habe Dir doch schon gesagt daß sowas gerne im Compiler/IDE-Forum diskutiert werden kann. Vom Standard ist es nicht gedeckt. Mich verwundert auch ein wenig daß Du da offenbar Deine persönliche Meinung über Deine Aufgaben als Moderator stellst. Aber sei's drum.

    Du hast komische Ansichten darüber, wie ein Forum oder dessen Moderation funktioniert. Ich versuche dem Fragesteller bestmöglich zu helfen, und mit den anderen Diskussionsteilnehmern zu argumentieren. Denkst du nicht, dass ist das Ziel?

    In diesem Fall nimmt die Hilfe die Form einer Warnung an, dass man höllisch aufpassen muss, wenn man deinen Code übernehmen will. Mit einer Begründung, warum das so ist, und wieso ich ihn deswegen für ein schlechtes Vorbild halte.



  • @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Du hast komische Ansichten darüber, wie ein Forum oder dessen Moderation funktioniert.

    Das ist echt quatsch. Das du als 'Profi' aber den Tipp gibst, den Standard nur dann einzuhalten, wenn es einem gerade in den Kram passt, finde ich allerdings auch sehr befremdlich.



  • @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Du hast komische Ansichten darüber, wie ein Forum oder dessen Moderation funktioniert.

    Findest Du? Ich nicht. Stellt man diese Frage im Kontext vom Standard muss man sagen "Kannst Du machen, wundere Dich aber nicht wenns knallt.". Stellt man sie betreffend einer Erweiterung des Compilers XY kann man diese diskutieren. Mischen bringts nicht wirklich.



  • Ich find´s auch sehr seltsam, dass eigentlich immer am Standard festgehalten wird und plötzlich Compilererweiterungen empfohlen werden. Das Blöde an der Sache ist, dass das auch alle anderen Compiler berschwerdefrei fressen.


  • Mod

    Wir sind aber nicht hier, um den Standard zum heiligen Selbstzweck zu erheben. Beziehungsweise, ich (und einige andere) sind nicht deswegen hier, andere schon. Ich bin hier, um dem TE zu erklären, welche Lösungen in der Praxis warum empfehlenswert sind und welche nicht. Das ist nicht richtig oder falsch im Sinne von Forennutzung, sondern eine andere Art, Fragen zu beantworten. Der TE kann dann entscheiden, welche Lösung er bevorzugt. Für und wider der verschiedenen Ansätze wurden schließlich ausgiebig (und größtenteils auch sachlich) diskutiert.


  • Mod

    @DocShoe sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Ich find´s auch sehr seltsam, dass eigentlich immer am Standard festgehalten wird und plötzlich Compilererweiterungen empfohlen werden. Das Blöde an der Sache ist, dass das auch alle anderen Compiler berschwerdefrei fressen.

    Es gibt halt Sachen, die funktionieren praktisch immer, obwohl sie theoretisch nicht vom Standard gedeckt sind, sind aber gleichzeitg besser als strikt standardkonforme Lösungen, solange sie funktionieren. Bei wieder anderen Sachen hat es wiederum keine Nachteile, sich strikt standardkonform zu verhalten, daher wäre es dumm, es nicht zu tun. Und noch wieder andere Fälle sehen so aus, als wären sie besser als strikt standardkonforme Lösungen, aber in der Praxis funktionieren sie dann doch nicht.



  • @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    Es gibt halt Sachen, die funktionieren praktisch immer, [...]

    Dann halte das eben wie Du willst. In einem Forum über Standard-C++ unions zum Type Punning zu empfehlen ist und bleibt ...

    @SeppJ sagte in Unions oder doch Bit-Shift und Bit-Operationen:

    (und größtenteils auch sachlich)

    Liest sich wie ein Vorwurf ich wäre unsachlich geworden. Eigentlich warte ich noch auf eine Entschuldigung Deinerseits.



  • Ab C++20 gibt es dafür dann std::bit_cast<To, From>.


Anmelden zum Antworten