Arrays mit 0 Einträgen, warum verboten?



  • Spricht was gegen

    struct UDPPacket 
    { 
    	unsigned long m_lMessageID; 
    	unsigned short m_shMessageType; 
    	unsigned short m_shSize; 
    	char **m_data; 
    };
    

    ?



  • Das wär die erste Lösung, die er genannt hat. Nachteil: Doppelte Allokation, komplizierteres Einlesen.



  • wie wärs mit 2 Structs einem mit m_data und einem ohne ?

    Devil



  • Bashar schrieb:

    Das wär die erste Lösung, die er genannt hat. Nachteil: Doppelte Allokation, komplizierteres Einlesen.

    Ich sehe das so, das er ne Struktur hat und die Variable missbraucht um den Anfang eines beliebig grossen blocks zu bestimmen.
    Bei allen anderen dingen komme ich doch wieder auf doppelte Allocation.



  • ich würde alles über methoden machen
    z.b.

    class UDPPacket
    {
        unsigned long messageId() const
        {
            return *reinterpret_cast<unsigned long*>( this );
        }
    
        unsigned short messageType() const
        {
            return *reinterpret_cast<unsigned short*>( static_cast<char *>( this ) + 4 );
        }
    
        unsigned short size() const
        {
            return *reinterpret_cast<unsigned short*>( static_cast<char *>( this ) + 6 );
        }
    
        void * data()
        {
            return static_cast<char *>( this ) + 8;
        }
    };
    

    man müsste aber noch überlegen wie man das ganze leichter warbar macht, denn bei änderungen der layout muss man viele zahlen ändern



  • Hi,

    @Knueddelbär: Nein, die Länge des Headers ist ja vorgegeben, nur die Länge des Datenpakets nicht.

    @Gerard: Sorry, aber was soll das bringen?

    Danke für eure Antworten! 🙂

    ChrisM



  • ChrisM schrieb:

    Hi,

    @Knueddelbär: Nein, die Länge des Headers ist ja vorgegeben, nur die Länge des Datenpakets nicht.

    UDPPacket* pkt = reinterpret_cast<UDPPacket*>(new char[sizeof(UDPPacket) + dataSize]);

    Für was brauchst Du denn die Variable m_data wenn nicht für die Anfangsadresse des Speichers ? Im moment macht das für mich keinerlei sinn



  • IIRC muß ein Datenelement immer sizeof() != 0 haben (IIRC^2 weil der Stnadard eine begrenzte Adreßeindeutigkeit garantiert - aber hier wird's schon arg duster mit den Erinnerungen)

    Warum allozierst du nicht nur den Header für "datenfreie" Pakete? Ob und wieviel Daten da sind, mußt du ja eh aus dem header rausbekommen.

    Das offset von m-data bekommst du (getrickst) mit

    (char *) &(((UDPPacket *)0)->m_data) - (char *)((UDPPacket *)0)
    

    ist nicht ganz legal (eigentlich darfst du nen NULL-Zeiger nicht dereferenzieren), aber rechnet ja eh der Compiler aus 🙄

    Legal kannst aber auch einfach (in anlehnung an gerhard)

    #pragma pack(push,1) // byte-alignment - compiler-abhängig!
    struct UDPPacket 
    { 
        unsigned long m_lMessageID; 
        unsigned short m_shMessageType; 
        unsigned short m_shSize; 
        char *   data() { return ((char *)this) + sizeof(*this); }
    };
    #pragma pack(pop)
    

    [/code]

    da kannst du gut noch ein _ASSERT einfügen, ob die entsperchende Message überhaupt daten haben darf. Ist m.E. ein guter kompromiß.



  • Hi,

    OK, danke, die Lösung gefällt mir. 😉

    ChrisM



  • ich habe mal wegen dieser warnung nachgelesen,
    das mit dem [0] ist eine erweiterung von microsoft, die wurde mal vor jahren eingeführt,
    wenn man die microsoft extensions mit dem kompilerschalter /Za ausschaltet bekommt man eine fehlermeldung, aber mit der extension (/Ze), welche auch std.mässig aktiviert ist, bekomme ich jenach kompilerversion keine meldung oder nur diese warnung, das es sich eben um eine extension handelt,
    ich habe auch mal den metrowerks codewarrior probiert, und der kommt auch damit klar, ohne eine warnung,
    also kannst du sicher diese variante ohne probleme benutzen, du solltest nur prüfen, ob die von dir verwendeten kompiler sie unterstützen



  • bozo schrieb:

    ich habe mal wegen dieser warnung nachgelesen,
    das mit dem [0] ist eine erweiterung von microsoft, die wurde mal vor jahren eingeführt

    Hehe klar, und Tolkien hat die Orks von DSA geklaut.



  • @Bashar
    dann schau doch in die msdn, es sieht dort ganz danach aus

    hier noch was aus der msdn:

    The given member in the structure or union contains an array that does not have a subscript or that has a zero subscript. This kind of array is legal only as the last member of a structure or union.

    also geht auch folgendes:

    struct UDPPacket 
    { 
        unsigned long m_lMessageID; 
        unsigned short m_shMessageType; 
        unsigned short m_shSize; 
        char m_data[]; 
    };
    

    habe es mit vs und cw getestet, es geht



  • @bashar - hey! Flim Flam Funkel Licht ins Dunkel...
    Ach ja! 🕶



  • bozo schrieb:

    dann schau doch in die msdn, es sieht dort ganz danach aus

    Das wurde unter Unix schon gemacht, als Bill Gates noch im College gebettelt hat, an den Computer zu dürfen.



  • ChrisM schrieb:

    @Gerard: Sorry, aber was soll das bringen?

    keine doppelte allokation, einlesen ist leicht und keine probleme mit padding bytes, der impelemnetierungs aufwand ist aber etwas größer



  • Könnte ich dies vorschlagen:

    struct UDPPacket
    {
        unsigned long m_lMessageID;
        unsigned short m_shMessageType;
        unsigned short m_shSize;
        char&at(unsigned int a){return ((char*)this)[sizeof(UDPPacket)+a];}
    };
    


  • Das gehört zwar nicht zum Thema, aber warum castest du bei new()?



  • Hi,

    danke, meine Paketstruktur/-klasse geht jetzt, dank kingruedi sogar mit Reference Couting Smart Pointer. 🙂

    ChrisM



  • ChrisM schrieb:

    danke, meine Paketstruktur/-klasse geht jetzt, dank kingruedi sogar mit Reference Couting Smart Pointer. 🙂

    Reference Couting in multithread umgebeungen soll nicht so der renner sein, zumidestenz weiß ich das von strings
    außerdem bevor du refcount einbaust solltes du echt überlegen ob du das brauchst, es erzeugt probleme und es bringt dich auch nicht den ziel näher (etwas arbeitendes), wenn jemand refcounting haben will dann soll der boost::shared_ptr oder sonst was benutzen


Anmelden zum Antworten