Neuer Datentyp: 48-Bit Int



  • NeoInferno schrieb:

    du könntest mit einem 6 Byte Char-Array deine 48Bit simulieren, und Bit für Bit "reinshiften"( mit <<). Das ganze evtl. mit std::vector und als Klasse funktioniert bestimmt super

    std::vector ist hier allerdings keine gute Lösung. Dynamisches Speicherhandling ist einfach zu viel Overhead für so einen simplen Datentyp. Da passt, wenn schon 'ne Klasse benutzt werden soll, boost::array besser.

    Honolulu schrieb:

    Erstmal danke für eure Antworten! Bitfielfs habe ich auch schon in Betracht gezogen, nur gibt mir VC++ jedesmal einen Error, wenn das Bitfield grösser als 32 ist.

    Das liegt daran, dass das Bitfeld nicht grösser sein kann als der eigentliche Datentyp.

    Doppler schrieb:

    Nimm doch einfach double, das hat 8 Bytes

    Erstmal wird nirgendwo festgelegt, dass double 8 Byte Datenbreite hat. Und selbst, wenn dem so ist und 1 Byte 8 Bits hat, dann sind das wieviel Bits? 48? 🙄

    Doppler schrieb:

    Wenns dich nicht stört daß die Genauigkeit etwas leidet

    Das lässt deinen Vorschlag vollkommen sterben. Bei Gleitkommazahlen kann man ja eínen gewissen Genauigkeitsverlust noch in Kauf nehmen. Bei ganzen Zahlen aber mit Sicherheit nicht.
    Wobei noch angemerkt sei, dass eine 64 Bit Gleitkommazahl nach IEEE eine 52 Bit Mantisse hat. Demzufolge musst du nicht mal auf Genauigkeit verzichten.
    Aber wie gesagt, eine 64 Bit Gleitkommazahl ist Blödsinn. Dan kannst du auch gleich eine 64 Bit Ganzzahl nehmen.



  • groovemaster schrieb:

    Doppler schrieb:

    Nimm doch einfach double, das hat 8 Bytes

    Erstmal wird nirgendwo festgelegt, dass double 8 Byte Datenbreite hat.

    Natürlich. Der IEEE Standard schreibt vor, daß eine Fliesskommazahl "Double Precision" aus 64 Bits besteht. Wenn sich ein Compiler nicht dran hält, weil es der bescheuerte C++ Standard eventuell nicht vorsieht, dann ist das eine andere Sache.

    groovemaster schrieb:

    Und selbst, wenn dem so ist und 1 Byte 8 Bits hat, dann sind das wieviel Bits? 48? 🙄

    Steigst du nur in ein Auto, wenn schon drei Personen drin sitzen? Es gibt vernünftige Argumente gegen die Nutzung von double, aber davon hast du nicht eins genannt. Typisch groovemaster: Erstmal alles für Blödsinn erklären was sich seinem beschränkten Verstand entzieht.



  • die groovemaster-methode ließe sich noch vereinfachen. die int48-klasse bräuchte nur benutzerdefinierte konversionen von und nach int64 zu enthalten. der compiler würde den rest dann automatisch erledigen 😃

    außerdem müsste man noch ein/ausgabe-operatoren für cin/cout schreiben.



  • ich hab da mal was gebastelt:

    #include<iostream>
    
    using namespace std;
    
    typedef unsigned __int64 uint_64;
    
    class uint48
    {
      unsigned char value[6];
    
      public:
      uint48 (uint_64 x);
      operator uint_64 ();
    };
    
    uint48::uint48 (uint_64 x)
    {
      value[0]=((unsigned char*)&x)[0];
      value[1]=((unsigned char*)&x)[1];
      value[2]=((unsigned char*)&x)[2];
      value[3]=((unsigned char*)&x)[3];
      value[4]=((unsigned char*)&x)[4];
      value[5]=((unsigned char*)&x)[5];
    }
    
    uint48::operator uint_64 ()
    {
      return   (uint_64)value[0]
            +(((uint_64)value[1])<< 8)
            +(((uint_64)value[2])<<16)
            +(((uint_64)value[3])<<24)
            +(((uint_64)value[4])<<32)
            +(((uint_64)value[5])<<40);
    }
    
    ostream
    &operator<< (ostream &os, uint_64 x)
    {
      if(x<10)
        os<<(unsigned)x;
      else
        os<<x/10<<x%10;
    
      return os;
    }
    
    void
    main ()
    {
      uint48 x=100000000001,y=200000000002;
    
      cout<<"sizeof(uint48)="<<sizeof(uint48)<<endl;
      cout<<x<<"+"<<y<<"="<<x+y<<endl;
    }
    

    das funzt auch schon ganz gut mit meinem VC++ 6.0. es fehlen aber noch vernünftige ein/ausgabe-operatoren und auch sonst muß noch dran gearbeitet werden. ich hab auch erst mal nur ein uint48 anstatt eines int48 programmiert, weil ichs mir mit dem weglassen des vorzeichens erst mal einfacher machen wollte. man kann aber natürlich genauso ein int48 implementieren.



  • Verdoppler schrieb:

    groovemaster schrieb:

    Doppler schrieb:

    Nimm doch einfach double, das hat 8 Bytes

    Erstmal wird nirgendwo festgelegt, dass double 8 Byte Datenbreite hat.

    Natürlich. Der IEEE Standard schreibt vor, daß eine Fliesskommazahl "Double Precision" aus 64 Bits besteht.

    Wir sind hier aber nicht im IEEE Forum, sondern bei C++. Und da wird die genaue Grösse von double nunmal nicht festgelegt. double muss nur mindestens soviel Präzision wie float haben. Zudem muss ja nicht auf jeder Plattform eine Gleitkommazahl nach IEEE dargestellt werden. 😉

    Verdoppler schrieb:

    Steigst du nur in ein Auto, wenn schon drei Personen drin sitzen?

    Versteh ich nicht. Kannst du mir mal aufgrund meines "beschränkten Verstandes" erklären, was das mit dem Thema zu tun hat?

    Verdoppler schrieb:

    Es gibt vernünftige Argumente gegen die Nutzung von double, aber davon hast du nicht eins genannt.

    Sry, wenn ich dich in deiner Ehre gekränkt hab. Aber wenn du Unsinn redest, dann solltest du auch mit Kritik leben können. Daran solltest du neben deinen Argumenten noch etwas arbeiten. 😉
    Du kannst mir die vernünftigen Argumente aber auch gerne nennen, bin immer bereit, was Neues zu lernen.
    Und wenn sich bei dir der Frust über die eigene Unerfahrenheit etwas gelegt hat, dann liess meinen Beitrag nochmal durch. Dann werden dir die vernünftigen Argumenten sicher bewusst. 💡 Wir glauben an dich, du schaffst das schon.

    @Konfusius
    Du solltest noch op= implementieren.
    Ansonsten

    void
    main ()
    

    🙄 🙂


  • Mod

    Konfusius schrieb:

    uint48::uint48 (uint_64 x)
    {
      value[0]=((unsigned char*)&x)[0];
      value[1]=((unsigned char*)&x)[1];
      value[2]=((unsigned char*)&x)[2];
      value[3]=((unsigned char*)&x)[3];
      value[4]=((unsigned char*)&x)[4];
      value[5]=((unsigned char*)&x)[5];
    }
    

    wenn schon unportabel mit tausenden casts dann bitte richtig unportabel und etwas effizienter 😉

    uint48::uint48 (uint_64 x)
    {
      *(unsigned*)value=x; // kein cast auf der rechten seite nötig
      ((unsigned short*)value)[2]=((unsigned short*)&x)[2];
    }
    


  • @groovemaster

    Du solltest noch op= implementieren.

    ist nicht nötig. der compiler nimmt dann automatisch den default-copy-konstruktor. und da die klasse keine resourcen alloziert genügt der ja völlig.

    @camper

    1. wie das ohne casts gehen soll mußt du mir mal erklären. und wenn schon casts dann besser explizit als implizit. man könnte höchstens monieren, daß ich nicht c++-mäßige static_cast<>'s verwendet habe. aber dann wärs noch unleserlicher geworden und es hätte dich noch mehr gestört.

    2. was daran unportabel ist mußt du mir auch nochmal erklären.

    3. die sache mit der effizienz ist schon richtig. hätte besser unsigned short value[3] anstatt unsigned char value[6] nehmen sollen. aber ich hab ja auch geschrieben, daß an dem code noch gearbeitet werden muß :p


  • Mod

    Konfusius schrieb:

    @camper

    1. wie das ohne casts gehen soll mußt du mir mal erklären. und wenn schon casts dann besser explizit als implizit. man könnte höchstens monieren, daß ich nicht c++-mäßige static_cast<>'s verwendet habe. aber dann wärs noch unleserlicher geworden und es hätte dich noch mehr gestört.

    mit >>

    value[0]=x;
      value[1]=x>>CHAR_BIT;
    // etc...
    
    1. was daran unportabel ist mußt du mir auch nochmal erklären.

    byteorder - auf big endian maschinen würdest du die niederwertigen 16 bit des ursprünglichen 64bit integers wegwerfen.

    1. die sache mit der effizienz ist schon richtig. hätte besser unsigned short value[3] anstatt unsigned char value[6] nehmen sollen. aber ich hab ja auch geschrieben, daß an dem code noch gearbeitet werden muß :p

    war auch kein allzu ernst zu nehmender beitrag von mir 🙂



  • mal ein paar unwesentliche gedanken dazu:

    #include<iostream> 
    
    using namespace std; 
    
    typedef unsigned __int64 u64;
    
    class u48 
    { 
        private:
        u64 read() const
        {//TODO: wilde casts und union zum konvertieren vorgesehen, aber 
        //sollte erstmal auch so gehen. aufpassen, daß casts nicht durch 
        //bad alignment auf ia64 unendlich langsam werden und lauter so 
        //sachen halt.
            return (u64(data[0])<<0)|(u64(data[1])<<16)|(u64(data[2])<<32);
        }
        void write(u64 x)
        {
            data[0]=x>>0;
            data[1]=x>>16;
            data[2]=x>>32;
        }
        unsigned int data[3];
        public: 
        u48 (u64 x)
        {
            write(x);
        }
        operator u64 () const
        {
            return read();
        }
    
        u48& operator+=(u48 const& b)
        {
            write(read()+b.read());
            return *this;
        }
        friend u48 operator+(u48 a,u48 b)
        {
            return u48(a)+=b;
        }
        //rest sollte easy sein. 
    }; 
    
    int main () 
    { 
      u48 x=100000000001ull,y=200000000002ull; 
    
      cout<<"sizeof(u48)="<<sizeof(u48)<<endl; 
      cout<<x<<"+"<<y<<"="<<x+y<<endl; 
    }
    


  • Konfusius schrieb:

    @groovemaster

    Du solltest noch op= implementieren.

    ist nicht nötig. der compiler nimmt dann automatisch den default-copy-konstruktor.

    Was denn nun, default- oder copy-ctor? 🙂
    Schon klar, was du meinst. Aber mit op= könnte es durchaus effizienter sein, wenn der Compiler es nicht schafft, das temporäre Objekt vernünftig wegzuoptimieren.

    Konfusius schrieb:

    man könnte höchstens monieren, daß ich nicht c++-mäßige static_cast<>'s verwendet habe. aber dann wärs noch unleserlicher geworden

    Nicht unbedingt.

    value[0]=((unsigned char*)&x)[0];
    value[0]=reinterpret_cast<unsigned char*>(&x)[0];
    

    Ich finde zB keine Zeile wirklich leserlicher.

    volkard schrieb:

    unsigned int data[3];
    

    Immer noch DOS am laufen? 😃



  • groovemaster schrieb:

    volkard schrieb:

    unsigned int data[3];
    

    Immer noch DOS am laufen? 😃

    lol


  • Mod

    gibt es eigentlich eine garantie, dass sizeof(u48) tatsächlich nur 6byte ist (auf den üblichen plattformen) ? immerhin ist es kein POD. diesbzgl. ist mir sowieso nicht ganz klar, was gefordert ist:

    a) der wertebereich des typs entspricht genau dem eines 48bit unsigned integers, also 0..2^^48-1
    b) der typ beansprucht genau 48bit speicher und padding in arrays ist verboten.

    falls nur a) gefordert ist, könnte man, wie erwähnt, ohne weiters bitfelder benutzen, was den vorteil hat, dass der compiler damit direkt umgehen kann:

    typedef unsigned long long u64;
    
    struct u48 { u64 value:48; };
    

    das hat allerdings dieselben speicheranforderungen wie ein 64bit integer, also ist b) nicht erfüllt. zum rechnen muss man jetzt bezug auf value nehmen, oder man baut eben eine ganze klasse mit schönem interface wie oben drumherum - dann ist es aber kein POD mehr, was evtl. ungünstig ist.



  • @camper: Das Alignment ist bei allen guten Compilern einstellbar, somit sollte das keine 64 Bits benötigen, oder? Trotzdem wärs wohl sicherer die Klassenvariante zu benützen.

    MfG SideWinder



  • camper schrieb:

    gibt es eigentlich eine garantie, dass sizeof(u48) tatsächlich nur 6byte ist (auf den üblichen plattformen) ? immerhin ist es kein POD.

    Ja, solange keine virtuellen Funktionen benutzt werden und der Compiler Padding verhindert, sollte es bzgl. der Grösse keine Probleme geben.

    camper schrieb:

    diesbzgl. ist mir sowieso nicht ganz klar, was gefordert ist:

    a) der wertebereich des typs entspricht genau dem eines 48bit unsigned integers, also 0..2^^48-1
    b) der typ beansprucht genau 48bit speicher und padding in arrays ist verboten.

    Also ich hab es so verstanden, dass b) gefordert war. Aber anstatt hier weiter zu raten, sollte Honolulu noch mal genau sagen, was er will. Mehrere Lösungsansätze hat er ja jetzt.

    camper schrieb:

    dann ist es aber kein POD mehr, was evtl. ungünstig ist.

    Wie gesagt, ich sehe darin keine Probleme.


  • Mod

    'sollte' war mir schon klar - die frage war nur, ob es irgendwelche garantien gibt.

    bzgl. padding - alignment das kann man sicher einstellen, ich glaube mich aber dunkel zu erinnern, dass bitfelder immer den bereich des zugrundeliegenden typs benötigen - irgendwie muss der compiler nach all der bitschieberei und -maskiererei ja darauf zugreifen. ich lasse mich aber gern korrigieren 🙂

    ein problem mit nicht-PODs ist, dass keine statische initilisierung stattfinden kann, das zumindest könnte unschön sein - wobei man ja problemlos auch zwei typen definieren könnte - eine als POD für solche zwecke und eine andere für das normale rechen.



  • camper schrieb:

    'sollte' war mir schon klar - die frage war nur, ob es irgendwelche garantien gibt.

    Was meinst du mit Garantien? So richtig versteh ich deine Bedenken nicht. Laut Standard, IIRC, werden Arrayelemente immer direkt hintereinander angeordnet, zB

    unsigned short data[3];
    

    sind 3 unsigned shorts und kein Bit mehr. Wenn dazu noch struct/class Padding durch den Compiler verhindert wird, wo soll also zusätzlicher Speicher verbraucht werden?

    camper schrieb:

    bzgl. padding - alignment das kann man sicher einstellen, ich glaube mich aber dunkel zu erinnern, dass bitfelder immer den bereich des zugrundeliegenden typs benötigen - irgendwie muss der compiler nach all der bitschieberei und -maskiererei ja darauf zugreifen. ich lasse mich aber gern korrigieren 🙂

    Padding bezog sich im Kontext ja auch nicht auf Bitfelder.

    camper schrieb:

    ein problem mit nicht-PODs ist, dass keine statische initilisierung stattfinden kann, das zumindest könnte unschön sein - wobei man ja problemlos auch zwei typen definieren könnte - eine als POD für solche zwecke und eine andere für das normale rechen.

    Mit statische initilisierung meinst du wahrscheinlich so eine initializer-list

    uint48 a = {1, 2, 3};
    

    Aber, da denkst du einfach zu umständlich. Ein uint48 (oder wie immer der Typen dann heissen mag) wird genauso gehandelt wie andere Ganzzahltypen auch. Du schreibst zB einfach

    uint48 a = 10;
    

    Wieviel und welche Member uint48 hat, hat dich überhaupt nicht zu interessieren.


  • Mod

    mit statischer initialisierung meine ich statische intialisierung (die in form einer solchen initialisiererliste stattfindet, aber das ist unwesentlich) - welche vor der dynamischen initialisierung stattfindet. falls ich irgendwelche globalen objekte haben, die bei der konstruktion solche 48bit integer brauchen, kann ich sonst nicht sicher sein, dass diese intialisiert sind, wenn sie nicht in der selben ÜE und vor dem betreffenden objekt definiert sind. sonst müsste man noch tausende kniffe ala iostream anwenden - ein bisschen viel aufwand für den zweck.

    Wenn dazu noch struct/class Padding durch den Compiler verhindert wird, wo soll also zusätzlicher Speicher verbraucht werden?

    padding und alignment sind zwei verschiedene dinge - auch wenn ersteres i.d.r. letzterem dient. die frage ist, gibt es eine garantie, dass der compiler nicht noch irgendwelche versteckten felder benutzt für welchen zweck auch immer - einen gc zum beispiel. bereits das einstellen irgendwelchen alignments oder struct paddings ist ja genau genommen kein standard.



  • camper schrieb:

    mit statischer initialisierung meine ich statische intialisierung (die in form einer solchen initialisiererliste stattfindet, aber das ist unwesentlich)

    Ich hab dazu ja auch nur ein Beispiel konstruiert. Statische Intialisierung kann auch so aussehen

    static foo bar;
    

    Und foo muss hier kein POD sein. 😉

    camper schrieb:

    falls ich irgendwelche globalen objekte haben, die bei der konstruktion solche 48bit integer brauchen, kann ich sonst nicht sicher sein, dass diese intialisiert sind, wenn sie nicht in der selben ÜE und vor dem betreffenden objekt definiert sind. sonst müsste man noch tausende kniffe ala iostream anwenden - ein bisschen viel aufwand für den zweck.

    😕 So richtig versteh ich hier nicht, was du uns damit sagen willst.
    Um mal ein weiteres Besipiel zu bringen

    class uint48
    {
        //...
    };
    
    struct unser_globaler_typ_der_bei_der_konstruktion_solche_48bit_integer_braucht
    {
        int a;
        uint48 b;
        long c;
    };
    

    Und jetzt willst du davon ein globales Objekt erstellen, richtig?

    unser_globaler_typ_der_bei_der_konstruktion_solche_48bit_integer_braucht x;
    

    Wie du vielleicht weisst, werden Objekte mit static storage duration, was unser globales Objekt hat, nullinitialisiert. Willst du nun eine initializer-list benutzen, hast du natürlich ein Problem. Es gibt kein uint48 Literal. 🙂 Oder korrekt formuliert, ein non-aggregate (was unser uint48 ja ist) kann in so einer Liste nicht initialisiert werden. Man muss sich dann halt überlegen, ob man sowas braucht. Klar könnte man, wie du schon sagst, einen Typ als aggregate und einen als non-aggregate bereitstellen, so ähnlich wie bei DirectX

    struct uint48plain
    {
        unsigned short value[3];
    };
    
    class uint48
        : protected uint48plain
    {
        //...
    };
    

    Halt ich aber für keine schöne Lösung, da somit Implementationsdetails offen gelegt werden. Bei uint48plain mag das ja noch gewollt sein, bei uint48 aber nicht. Zudem wäre das Handling von uint48plain etwas umständlich und nicht so intuitiv wie mit den elementaren Typen.

    camper schrieb:

    die frage ist, gibt es eine garantie, dass der compiler nicht noch irgendwelche versteckten felder benutzt für welchen zweck auch immer

    Ja, die gibt es. Ansonsten würde ich meinen Compiler wegschmeissen. Das einzige Problem, was entstehen könnte, ist die Grösse der addressierbaren Einheiten. Wenn sich also 48 Bit nicht durch ein Vielfaches einer addressierbaren Einheit darstellen lässt. Da x86 kompatible Plattformen mit Vielfachen von 8 arbeiten, gibt es dort zB keine Probleme.

    camper schrieb:

    einen gc zum beispiel

    Standard C++ hat keinen GC.

    camper schrieb:

    bereits das einstellen irgendwelchen alignments oder struct paddings ist ja genau genommen kein standard

    Richtig, das wurde aber bereits erwähnt, das sich dies nur compiler-spezifisch realisieren lässt.


  • Mod

    groovemaster schrieb:

    Ich hab dazu ja auch nur ein Beispiel konstruiert. Statische Intialisierung kann auch so aussehen

    static foo bar;
    

    Und foo muss hier kein POD sein. 😉

    was soll das denn jetzt? das weisst du besser 😉 das static keyword hat doch nichts mit der initialisierung zu schaffen (nur insofern als static storage voraussetzung für static initilisiation ist).

    camper schrieb:

    falls ich irgendwelche globalen objekte haben, die bei der konstruktion solche 48bit integer brauchen, kann ich sonst nicht sicher sein, dass diese intialisiert sind, wenn sie nicht in der selben ÜE und vor dem betreffenden objekt definiert sind. sonst müsste man noch tausende kniffe ala iostream anwenden - ein bisschen viel aufwand für den zweck.

    😕 So richtig versteh ich hier nicht, was du uns damit sagen willst.

    ...

    ... das meinte ich gar nicht, aber ist auch ein guter punkt. die aussage soll ja nur sein, dass eben weder eine POD variante noch eine mit schönem interface, aber eben als nichtPOD, nicht alle bedürfnisse befriedigen kann.

    sinnfreies beispiel:

    // a.h
    struct uint48 {  /* schönes interface, kein POD ... */ };
    extern const uint48 xyz;
    
    // a.cpp
    #include "a.h"
    const uint48 xyz = 10;
    
    // b.cpp
    #include "a.h"
    
    struct X
    {
        uint48 x;
        X() : x( xyz ) { }
    };
    
    X x;
    

    wird xyz vor oder nach x initialisiert? es ist zwar richtig, dass alle objekte mit static storage beim start zero-initialisiert werden, aber das ist für nicht aggregate völlig bedeutungslos. das objekt lebt dann erst, nachdem der konstruktor ausgeführt wurde.

    camper schrieb:

    die frage ist, gibt es eine garantie, dass der compiler nicht noch irgendwelche versteckten felder benutzt für welchen zweck auch immer

    Ja, die gibt es.

    und das steht wo?

    camper schrieb:

    einen gc zum beispiel

    Standard C++ hat keinen GC.

    der standard erlaubt ausdrücklich gc.



  • camper schrieb:

    groovemaster schrieb:

    Ich hab dazu ja auch nur ein Beispiel konstruiert. Statische Intialisierung kann auch so aussehen

    static foo bar;
    

    Und foo muss hier kein POD sein. 😉

    was soll das denn jetzt?

    Das Statement war eher in Verbindung mit deiner Aussage bzgl.

    camper schrieb:

    ein problem mit nicht-PODs ist, dass keine statische initilisierung stattfinden kann

    gedacht.

    camper schrieb:

    das weisst du besser 😉 das static keyword hat doch nichts mit der initialisierung zu schaffen

    Doch, das hat es. Aber wenn's dich stört, dann denk es dir einfach weg und static storage duration dazu. (und lass deine Klugscheisserei aussen vor 😉 )

    camper schrieb:

    nur insofern als static storage voraussetzung für static initilisiation ist

    Das ist zwar richtig, aber eher irrelevant, da man von statischer Initialisierung sowieso nur bei nicht-lokalen Objekten spricht. Viel wichtiger ist die Tatsache, dass es sich um statische Initialisierung bei Nullinitialisierung oder Initialisierung mit konstanten Werten handelt.

    camper schrieb:

    sinnfreies beispiel:

    // a.h
    struct uint48 {  /* schönes interface, kein POD ... */ };
    extern const uint48 xyz;
    
    // a.cpp
    #include "a.h"
    const uint48 xyz = 10;
    
    // b.cpp
    #include "a.h"
    
    struct X
    {
        uint48 x;
        X() : x( xyz ) { }
    };
    
    X x;
    

    wird xyz vor oder nach x initialisiert?

    Das ist aber nicht spezifisch für die eigentliche Problematik. Du sprichst hier ein generelles Problem beim Initialisieren von globalen Objekten an.
    Auch wenn sich ein uint48 wie ein elementarer Typ benutzen lässt, so bleibt es doch ein non-POD mit all den verbundenen Konsequenzen. So wie es bei anderen Klassen auch der Fall ist. Das dürfte dem Op mittlerweile schon klar geworden sein.

    camper schrieb:

    und das steht wo?

    🙄 Nunja, ich hoffe, dass du noch nicht anfängst zu hyperventilieren. 🙂 Ansonsten bau dir ein static assert mit sizeof.

    der standard erlaubt ausdrücklich gc.

    Mag sein, diesbzgl. sind mir allerdings keine Quellen bekannt. Genauso wenig, dass die Implementation einfach so irgendwelche "unsichtbaren" Daten in die Klasse packen darf (bis auf Padding, um entsprechendes Alignment zu garantieren). Und wenn schon GC, dann werden benötigte Informationen mit Sicherheit an anderer Stelle gespeichert.


Anmelden zum Antworten