alignas



  • hallo leute

    folgender code:

    struct alignas(32) basic_control
    {
       HWND handle = nullptr;
       txl::rect rect;
       const unsigned short id;
    
       protected:
       basic_control(unsigned short tid) noexcept : id(tid) { }
    }; /* class basic_control */
    
    template<unsigned short ID>
    struct Control : public basic_control
    {
       Control(void) : basic_control(ID) { }
    };
    
    struct Controls
    {
       Control<0x1000> btn1;
       Control<0x1001> btn2;
       Control<0x1002> btn3;
       Control<0x1003> btn4;
    };
    
    ...
    
       Controls controls;
       int count = sizeof(controls) / sizeof(basic_control);
    
       basic_control *con = reinterpret_cast<basic_control*>(&controls);
    
       for(int i = 0; i < count; ++i)
       {
          con->rect.left = 12 + i;
          ++con;
       }
    

    durch alignas(32) stelle ich sicher das ich immer eine 4 byte ausrichtung hab.
    struct Controls sollte jetzt eigendlich im speicher gleich aufgebaut sein wie ein array.
    ist es nun standardkonform das ich dann mittels einen pointer darauf zugreife als wenn es ein
    echtes array waere ?

    Meep Meep


  • Mod

    durch alignas(32) stelle ich sicher das ich immer eine 4 byte ausrichtung hab.

    Eigentlich drückst du aus, dass du eine 32-Byte Ausrichtung wünschst.

    struct Controls sollte jetzt eigendlich im speicher gleich aufgebaut sein wie ein array.

    Das kann aber nicht mit Sicherheit gesagt werden. Zwar hat Controls möglicherweise Standardlayout (hängt von txl::rect ab), wodurch die Adresse des ersten Members stets der Adresse des vollständigen Objekts gleichen würde, Padding zwischen den Membern kann aber durchaus präsent sein. Lieber ein pack pragma reinhauen.

    ist es nun standardkonform das ich dann mittels einen pointer darauf zugreife als wenn es ein echtes array waere ?

    Ohne Padding schon, da du die Zeiger lediglich inkrementierst, was gewissermaßen das aktuelle wording in [expr.add]/4 überlistet. Der eigentliche Knackpunkt liegt jedoch woanders:

    [basic.compound]/3 schrieb:

    If an object of type T is located at an address A , a pointer of type cv T* whose value is the address A is said to point to that object, regardless of how the value was obtained. [ Note: For instance, the address one past the end of an array (5.7) would be considered to point to an unrelated object of the array’s element type that might be located at that address. There are further restrictions on pointers to objects with dynamic storage duration; see 3.7.4.3. — end note ]

    Dieser Paragraph wird nun durch P0137R0 abgeändert:

    Every value of pointer type is one of the following:

    • a pointer to an object or function (the pointer is said to point to the object or function), or
    • a pointer past the end of an object (5.3.1 expr.unary.op), or
    • the null pointer value (4.10 conv.ptr) for that type, or
    • an invalid pointer value.

    A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory (1.7 intro.memory) that the object occupies or the first byte in memory after the end of the storage occupied by the object, respectively . [ Note: A pointer past the end of an object (5.7) is not considered to point to an unrelated object of the object's type that might be located at that address. […] — end note]

    Mit dem neuen Text hat dein Programm undefiniertes Verhalten; ++con zeigt nicht auf das zweite Objekt, sondern ist ein dem ersten Objekt entsprechender past-the-end Zeiger.



  • Meep Meep schrieb:

    ist es nun standardkonform das ich dann mittels einen pointer darauf zugreife als wenn es ein
    echtes array waere ?

    Nein. Wenn du ein Array willst, dann mach ein Array...


Log in to reply