Cast von struct in int* sicher??



  • Hi,

    ich habe folgenden Code und möchte gerne wissen, ob der Cast wirklich 100% sicher ist, insbesondere auf verschiedenen Machinen (Windows / Linux):

    typedef signed long  int32;
    
    // Indices des Dreiecks
    typedef struct _Triangle
    {
        int32 i;
        int32 j;
        int32 k;
    }Triangle;
    
    // ...
    int32 Class::Method(const Triangle *const triangle)
    {
        const int32* indices = (const int32*)triangle;  // to be able to iterate
        for(int i = 0; i < 3; i++)
        {
            // ...
        }
    }
    

    Ich dachte, da Triangle nur Daten enthält, müsste das im Speicher eigentlich genauso angeordnet sein, wie ein int32*. Ist das korrekt?!?! Auf meinem WinXP-Rechner klappt das, es muss aber GARANTIERT auch auf in jeder anderen Umgebung funktionieren.

    Wenn mir jemand sagt, dass das gefährlich ist, mache ich es anders...

    Danke,
    Felix



  • Ob das klappt, bin ich mir nicht sicher - durchaus möglich, daß dir das Padding auf bestimmten Rechnern dein Design durcheinanderbringt.

    Du könntest deiner struct aber eine Zugriffsfunktion spendieren, die einen Index-Zugriff in eine der drei Membervariablen übersetzt:

    struct Triangle
    {
      int i,j,k;
      int& operator[](int v)
      {
        return (v==0)?i: (v==1)?j:k;
      }
    };
    


  • int32 Class::Method(const Triangle *const triangle)

    Ich geh mal davon aus dass du C++ verwendest ...

    Warum der cast ?

    Was erreichst du durch den cast ?
    Das du dein triangle wie ein Array (zeiger auf x hintereinanderliegende elemente) verwenden kannst ....

    Wie erreichst du das besser ?

    Ideale variante: du nimmst gleich wirklich nen Array !

    class Triangle
    {
    public:
        // Konstruktoren destruktoren die man so braucht 
    
        // Zugriff auf die rohen daten, falls man mal irgend ne C-Schnittstelle 
    befuellen muss
        const int32 * c_data() const {return adata;}
        // Index opeerator ueberladen, damit die klasse selber wie nen Array behandeln kannst 
        const int32 & operator[](size_t index) const {return adata[index];}
        int32 & operator[](size_t index){return adata[index];}
    private:
        int32 adata[3]; 
    };
    

    Falls du irgendwo doch dein i j k brauchst, mir fallen aaber ehrlich keine gruende ein, dann mach dein struct einfach so zur klasse und verwende nur die index operatoren ....

    Also bleibt nur die frage, warum brauchst du eigentlich die struct ???

    Ciao ..



  • Du darfst die Adresse eines structs in die Adresse des Typs des ersten Members casten. Das Dereferenzieren dieser Adresse ist dann zulässig. Zugriff auf die dahinterliegenden Felder garantiert das aber nicht. Z.B. auf einer 64Bit Maschine sieht das schon viel anders aus. Oder mit einem per #pragma erzwungenem Padding. Es ist auf jeden Fall nicht standardkonform und du hast keine Garantie, dass es überall funktioniert.

    Eine Alternative wäre das hier:

    struct X
    {
       int x[3];
    };
    


  • Ok, danke für die Antwort. Also: Ich habe die Datenstrukturen festgelegt durch eine Bibliothek. An dem Struct Triangle kann ich nichts ändern. Und insg. sollte der Code möglichst schnell sein. Ich hätte auch gerne ein Array, kann aber nix daran ändern, dass ich drei Variablen i, j, k habe :-(.

    Die einzige Möglichkeit, die ich noch sah, ist dreimal derselbe Code für i, j und k. Das fand ich aber auch nicht sehr gelungen...



  • Ok, also, da das ja anscheinend nicht so wirklich super ist, habe ich jetzt die drei Werte i,j,k einzeln getestet, ohne die Schleife. Ist auch nicht soo viel Code, insofern vertretbar, denke ich. Und wahrscheinlich sogar schneller ohne die ganzen Sprünge und die Zählvariable.

    Trotzdem danke 🙂



  • Das sicherste was machen kannst iss in dem falle die Struct zu wrappen ...
    Wenn es schnell sein soll, willst ja kopien vermeiden ....

    class TriangleWrapper
    {
    public:
        TriangleWrapper(Triangle & rx):rdata(rx){}
        ~TriangleWrapper(){}
        // Code von CStoll adaptiert ! :-) 
        int32& operator[](int v){return (v==0)?rdata.i: (v==1)?rdata.j:rdata.k;}
        // und um const variante ergaenzt 
        const int32& operator[] const (int v){return (v==0)?rdata.i: (v==1)?rdata.j:rdata.k;}
    private:
        Triangle & rdata;
    };
    

    Ciao ...


Anmelden zum Antworten