Arrays mit 0 Einträgen, warum verboten?
-
Ich denke, es liegt daran, dass Objekttypen immer eine Größe ungleich 0 haben müssen.
-
Hi,
schade.
Was würdet ihr dann machen?
- Daten woanders speichern und Zeiger darauf erstellen (Nachteil: Ich kann das Packet nicht mehr so wie es ist verschicken und muss pro Paket zweimal Speicher allokieren, bei einem großen Server mit vielen kleinen Paketen macht das schon was aus)
- Warnung ausschaltenChrisM
-
ChrisM schrieb:
Hi,
ja, aber dann hab ich ja immer mindestens ein Datenbit,
Schlimmer: Es ist ein Byte.
Entweder Du schreibst es also "ordentlich", oder lebst weiter mit der Warnung.
(In C hat für sowas eine eigene Schreibweise erfunden.)
-
Hi,
ja, ich meine doch ein Byte, halt ein char.
Ich schalte die Warnung jetzt einfach aus und überlade Kopierkonstruktor und =-Operator (die Standardversionen der beiden funktionieren mit meiner variablen Größe logischerweise nicht), wenn hier niemand mehr eine andere Lösung einfällt...
ChrisM
-
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ührtHehe klar, und Tolkien hat die Orks von DSA geklaut.
-
@Bashar
dann schau doch in die msdn, es sieht dort ganz danach aushier 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];} };