Kopieren eines arrays in einem struct hack



  • Hallo zusammen

    Ich habe eine struct das ein byte Array mit der größe 1 am ende der Struktur beinhlatet. Das man bekanntermaßen als "struct hack" bezeichnet.

    struct mystruct
    {
        int datasize;
        BYTE data[1];
    };
    

    möchte ich nun den Inhalt der structur in eine andere kopieren kann ich doch den Inhalt von data per memcpy übertragen.
    Frage wie allokiere ich hier den Speicher für die neue struct?
    Hier muss ich doch den Platz berücksichtigen die data einnimmt.

    Ach ja der neue Speicherbereich soll ein std::shared_ptr auf die Structur sein.


  • Mod

    Warum willst du in C++ komische C-Hacks machen?



  • Von wollen ist da keine Rede. Die structur bekomme ich so übergeben. (WinCC wenn dir das was sagt).
    Da die structur der Datentypen unterschiedlich ist bei verschiedenen Versionen möchte ich diese mit einer compilerdirectrive in eine einheitlich structur kopieren. Damit ich so viel wie möglich gemeinsamen Code habe.

    Das kopieren der einzelnen Member stellt nun kein Problem dar bis auf dieses array.

    Möglichkeit wäre sicher auch dass ich in der gemeinsamen einheitlichen structur eine eigene definiere und darin statt dem hack ein std::vector verwende. Oder?

    Wobei ich hier dann alle Stellen die bereits auf die Struktur zugreifen ändern müsste.


  • Mod

    Es ist zwar nicht mein Stil, auf Stackoverflowantworten zu verlinken, aber als ich an einer Lösung bastelte, musste ich (mangels Übung, weil man das fast nie braucht) nachschlagen, wie man Operator new pro Klasse mit Argumenten korrekt überlädt und aufruft. Und bin dabei direkt über die passende Antwort mit umfangreicher Erklärung zu deiner Frage gestolpert, die ich auch nicht besser geben könnte. Denn dies ist wahrscheinlich einer der ganz wenigen Fälle, wo man das Konstrukt brauchen würde. Insofern: https://stackoverflow.com/a/20290733/11208562

    Man könnte und sollte natürlich noch diskutieren, ob sich das überhaupt lohnt. Das Konstrukt ist immer noch sehr fehleranfällig und braucht vom Programmierer viel Aufmerksamkeit und Spezialwissen. Die Alternative wäre, die Struktur einmalig bei Übergabe in eine "normale" C++-Struktur zu überführen, mit der dann anderswo weiter gearbeitet wird. Das kostet etwas Laufzeit, aber würde sicher viel Zeit und Schmerz bei der Entwicklung des restlichen Programms sparen. Und es behebt auch das potentielle Problem, dass dieses ganze Konstrukt in C++ sowieso nicht so ganz gültig ist, und man potentiell unbehebbare Probleme mit undefined behavior bekommen könnte, selbst wenn es jetzt auf den meisten Compilern wahrscheinlich funktionieren sollte.



  • @booster
    Eine solche Structur kenne ich von der WinAPI: BITMAPINFO

    Eine 100% saubere Lösung kenne ich nicht, aber vielleicht hilft dies:

    #include <iostream>
    #include <Windows.h>
    #include <cstdint>
    #include <vector>
    
    
    
    struct mystruct
    {
    	int datasize;
    	BYTE data[1];
    };
    
    class EvilStruct
    {
    private:
    	std::vector<uint8_t> mStructBytes;
    
    public:
    	EvilStruct(int Size)
    	{
    		mStructBytes.resize(Size + sizeof(int));
    		get()->datasize = 0;
    	}
    
    	mystruct* get()		// keine schöne Funktion, da der Zeiger nur dann gültig bleibt wenn mStructBytes nicht verändert wird
    	{
    		return reinterpret_cast<mystruct*>(mStructBytes.data());
    	}
    };
    
    void Fill(mystruct* s)		// ich tippe mal einige Funktion von dir sehen so aus
    {
    	s->datasize = 10;
    	for (int i = 0; i < 10; i++)
    		s->data[i] = i;
    }
    
    void Print(const mystruct* s)
    {
    	for (int i = 0; i < s->datasize; i++)
    		printf("%i ", s->data[i]);
    	printf("\n");
    }
    
    int main()
    {	
    	EvilStruct ps(10);
    		
    	Fill(ps.get());
    	Print(ps.get());	
    	return 0;
    }
    


  • @SeppJ sagte in Kopieren eines arrays in einem struct hack:
    Die Alternative wäre, die Struktur einmalig bei Übergabe in eine "normale" C++-Struktur zu überführen, mit der dann anderswo weiter gearbeitet wird.

    Genau das ist das was ich gemeint habe. Und dann statt einem array gleich ein std::vector zu verwenden.
    Da ich ja erst zur Laufzeit weiß wie groß data ist.

    Wenn ich nen shared_ptr auf die neue Struktur haben will. Sollte es reichen

    make_shared<MyNewStruct>()
    

    aufzurufen. Die rudimentären datentypen zuzuweisen und beim vector den Standard Konstrutor aufzurufen.
    Mit übergabe des arrays und der größe aus datasize.

    Geht das?



  • Du meinst den Konstruktor mit dem Iterator-Paar (nicht den Standardkonstruktor):

    mystruct ms;
    std::vector<BYTE> vec(&ms.data[0], &ms.data[ms.datasize]);
    


  • @Th69

    Ja stimmt aber egal. In meiner struct kann ich ja eh keinen Constructor aufrufen.

    Ich habe es nun so gemacht:

    const auto spds = make_shared<mynewstruct>();
    spds->byData.insert(spds->byData.end(), &lpds->byData[0], &lpds->byData[lpds->dwDataSize]);
    

    wobei lpds die alte Struktur war.


Log in to reply