Zwei Strukturen auf gleichem Speicherplatz



  • Hallo
    Ich möchte auf die erste Struktur schreiben
    und dann von der zweiten Struktur lesen.
    Idealerweise liegen die Strukturen übereinander (gleicher Aufbau)
    Hat jemand eine Lösung?
    Gruß, Harald

    // CAN_Message PEAK
    typedef struct {
        DWORD ID;        // 11/29 Bit-Kennung
        BYTE  MSGTYPE;   // Bits aus MSGTYPEx*
        BYTE  LEN;       // Anzahl der gueltigen Datenbytes
        BYTE  DATA[8];   // Datenbytes 0..7
    } TPCANMsg;
    
    // CAN Message Ixxat
    typedef struct
    {
        DWORD  MsgId;      // 11/29 Bit-Kennung
        BYTE MsgType;      // Nachrichten Typ
        BYTE Length;       // Anzahl der Datenbytes 0-8
        BYTE Data[8];      // Datenbytes 0...7verwendet)
    } CANMESSAGE;
    


  • Im ersten Moment würde mit ein union in den Sinn kommen.

    In etwa:

    union CAN_Message
    {
        TPCANMsg   PEAK;
        CANMESSAGE Ixxat;
    };
    

    Habe aber selber noch keine unions benötigt um das zu validieren...



    1. Du machst einen harten Cast:
    TPCANMsg struct1 = /* ... */;
    CANMESSAGE *pstruct2 = (CANMESSAGE*)&struct1;
    pstruct2->MsgId ...
    

    EDIT: Ich seh jetzt erst, dass es um C++ statt um C geht. In dem Fall ist aus Stilgründen ein reinterpret_cast auf einen Referenztypen angesagt:

    CANMESSAGE &struct2 = reinterpret_cast<CANMESSAGE&>(struct1);
    struct2.MsgId ...
    
    1. Du packst beide in eine union:
    union bla {
      TPCANMsg struct1;
      CANMESSAGE struct2;
    } blub;
    
    blub.struct1.ID = 42;
    blub.struct2.MsgId /* => 42 */
    

    beides natürlich nicht vom Standard definiert, es sollte aber funktionieren, zumal die Strukturen identisches Layout haben.



  • Gibt mehrere Möglichkeiten:
    - du einigst dich darauf, nur eine von beiden zu nutzen, da der Aufbau ja identisch ist. Dagegen spricht eigentlich nur, wenn beide Definitionen nicht von dir stammen sondern aus irgendwelchen Bibliotheken (die beiden typedefs die du da hast sehen nach C-APIs aus). In dem Fall würde ich Adapter für eine oder beide Bibliotheken schreiben, die Umsetzung sollte ja nicht so schwer sein;

    - du schreibst Umwandlungsfunktionen von der einen in die andere Struktur und hoffst dass der Compiler das weitgehend wegoptimiert.

    - du benutzt union, das ist allerdings nur bei POD structs ratsam, wenn überhaupt.



  • Wenn eine der beiden Strukturen aus einer fremden Library stammt, so kann es sein, dass diese ein anderes Packaging hat, als Du erwartest. Der Effekt wäre, dass ein reinterpret_cast bzw. eine union eben nicht zu dem von Dir gewünschten Verhalten führen.
    Wen Du es trotzdem machst - so füge in Deinem Code mindesten ein BOOST_STATIC_ASSERT( sizeof(TPCANMsg) == sizeof(CANMESSAGE) ); ein.

    Der Vorschlag von Pumuckl ist in jedem Fall die sichere Variante.

    Andererseits schließe ich aus

    Andresen schrieb:

    Ich möchte auf die erste Struktur schreiben
    und dann von der zweiten Struktur lesen.

    dass kein anderes Programm oder andere Library in diese Typen schreibt oder aus ihnen liest.
    Wie kommt es dann zu den beiden unterschiedlichen Typen?

    Gruß
    Werner



  • Hallo
    Zuerst einmal vielen Dank für eure schnellen Antworten.
    Das Problem ist, das mein neues Programm sich aus zwei verschiedenen Programmen zusammensetzt. Nur ein Programm habe ich selbst geschrieben.
    In den Programmen werden die Strukturen mehrfach verwendet (Bibliotheken ??).
    Um die Änderungen minimal zu halten, habe ich mich jetzt entschlossen, vor Verwendung der Struktur ein Umkopieren vorzunehmen.
    Es läuft jetzt problemlos.

    void p_Ixxat_to_Peak(void)
    {
        myMsg.ID = MsgIxxat.MsgId;
        myMsg.MSGTYPE = MsgIxxat.MsgType;
        myMsg.LEN = MsgIxxat.Length;
        for(int i=7; i>=0; i--)
            myMsg.DATA[i] = MsgIxxat.Data[i];
    }
    ---------------------------------------------------------------------------
    void p_Peak_to_Ixxat(void)
    {
        MsgIxxat.MsgId = myMsg.ID;
        MsgIxxat.MsgType = myMsg.MSGTYPE;
        MsgIxxat.Length = myMsg.LEN;
        for(int i=7; i>=0; i--)
            MsgIxxat.Data[i] = myMsg.DATA[i];
    }
    

Anmelden zum Antworten