struct element rauslesen



  • Hallo,

    gibt es eine Möglichkeit die Elemente einer Struct zu nummerieren?

    struct element1 {
    
      unsigned int Type; 
      unsigned int State; 
      unsigned short Color; 
      unsigned short Wheel; 
    };
    

    Im Prinzip möchte ich gerne das dritte Element z.B. einer Struct auslesen können (was in diesem Fall Color darstellen würde). Ist das möglich ohne die genaue Bezeichnung (Color) zu kennen?

    gruß
    ingo



  • also z.B. wie bei einem Array?

    Die struct stellt in meinem beispiel die spalten einer tabelle dar - und als input parameter bekomme ich lediglich eine zahl (welche spalte ausgelesen werden soll)...

    ingo



  • gibt es eine Möglichkeit die Elemente einer Struct zu nummerieren?

    Da ist die Antwort (wie fast immer): Ja. Spannender hingegen schon die Frage, ob man auch portabel hinbekommt.

    Wenn ich dir jetzt verrate, daß sizeof(element1) sich ergibt als 2 * sizeof(int) + 2 * sizeof(short) , dann wirst du schon wittern, in welche Richtung das geht. Aber wozu das alles? Warum nicht gleich ein Array nehmen, das doch so freundlich auf ganzzahlige Indizierung reagiert?



  • Manchmal bin ich in der Nacht nicht müde. Dann packt mich der sportliche Ehrgeiz.

    dann wirst du schon wittern, in welche Richtung das geht

    Das will ich dir ersparen, also ein Beispiel:

    Aber zuerst der Haftungsausschluss: mein Compiler reiht die Teile einer Struktur im Speicher nacheinander, und zwar in Reihenfolge, in der sie deklariert wurden. Keine Ahnung, was der Standard oder andere Compiler dazu sagen.

    // deine Struktur
    struct element1 {
        unsigned int Type;
        unsigned int State;
        unsigned short Color;
        unsigned short Wheel;
    };
    
    // die Offsets der einzelnen Speicherbereiche in deiner Struktur
    // in Bytes
    int offsets [] = {
        0,
        sizeof(unsigned int),
        sizeof(unsigned int) + sizeof(unsigned int),
        sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned short)
    };
    
    // ein Makro, um einen Speicherbereich aus der Strukur herauszufrickeln
    // index ist ein Index für offsets, type brauche ich, um den Resultat-Zeiger richtig zu casten
    #define AT_INDEX(element, index, type) \
        (*(type*)(((char*)&element) + offsets[index]))
    
    // dann sage ich irgendwo:
    struct element1 e = { 100, 200, 300, 400 };
    
    // und greife so darauf zu:
    AT_INDEX(e, 1, unsigned int)  // ergibt 200 (uint)
    AT_INDEX(e, 4, unsigned short)  // ergibt 400 (ushort)
    

    Problem gelöst, Ehrgeiz befriedigt. Es folgt der ernsthafte Teil:

    Auf diese Weise ist es völlig unnötig, überhaupt eine Struktur zu verwenden. Ich könnte e auch als char[12] (Konstante für mein System) definieren. Oder als irgendwas anderes, was mehr als 11 Bytes an Platz braucht. Vielleicht hast du die Struktur nur verwendet, um auch shorts unterzubringen; ein Array könnte ja nur gleichartige Typen (also ints) enthalten. Für diesen Fall habe ich dir gleichzeitig ein Verfahren skizziert, um verschieden große Typen in einem Speicherbereich zusammenzufassen. Für alles weitere sollte ich aber wissen, was du eigentlich vorhast!



  • vielen dank für das Beispiel.

    die struct hab ich deshalb favorisiert, da innerhalb der struct sowohl integer als auch char strings vorhanden sein können. -> das funktioniert mit einem array leider nicht.

    ob alles nach einander im speicher abgelegt wird, das muss ich erstmal ausprobieren... allerdings ist es wie du schon sagtest nicht sicher...

    eine andere möglichkeit ist lediglich noch mit einem switch die spalte auszuwählen und entsprechend dann die jeweilige struct-variable aufzurufen...

    gruß
    ingo



  • Ja, dem sollte wohl so sein, das die Strukturelemente nacheinander im Speicher abgelegt werden. Das kenne ich auch so. Vielleicht steht ja auch was im draft, keine Ahnung.
    Sind jedoch Zeiger in der Struktur vorhanden, die auf dynamisch reservierten Speicherplatz verweisen, so ist dieser Speicherplatz außerhalb dieses Strukturbereichs.

    AT_INDEX(e, 4, unsigned short) // ergibt 400 (ushort)

    du meinst sicherlich AT_INDEX(e, 3, unsigned short) :p

    Dann musst du natürlich noch sicherstellen, das dir der Compiler keine Füllbytes in die Strukturen reinschiebt. Das ist meist bei ungeraden sizeof(struct foo) Werten der Fall.
    Notfalls kannst du mit der Anweisung
    #pragma pack(1)
    vor der Strukturdeklaration sicherstellen, das da keine Füllbytes reingeschrieben werden. Ansonsten bekommst du irgendwelche Überraschungswerte, nur nicht das, was du erwartest 😃
    Und ggf. mit #pragma pack() die default Ausrichtung wieder herstellen.
    🙂



  • frickel-flamer schrieb:

    Manchmal bin ich in der Nacht nicht müde. Dann packt mich der sportliche Ehrgeiz.

    naja, etwas schlaf hätte dir sicherlich gut getan. so umständlich (mit diesem offsets-array) hab' ich das noch nie gesehen.
    🙂



  • die struct hab ich deshalb favorisiert, da innerhalb der struct sowohl integer als auch char strings vorhanden sein können. -> das funktioniert mit einem array leider nicht.

    Deshalb würde ich in der Praxis auf die shorts pfeifen und lauter ints nehmen. Solange der Speicher nicht knapp wird wahrscheinlich die einfachste Lösung. Sonst kommt man halt nicht drum herum, sich zu merken, wie groß jedes Element im Bereich war.

    du meinst sicherlich AT_INDEX(e, 3, unsigned short)

    O ja.

    so umständlich (mit diesem offsets-array) hab' ich das noch nie gesehen

    Version 2 wird in der nächsten langen Nacht nachgereicht.
    🙂



  • das sieht mir alles nach einem mangelhaften softwaredesign aus. das lässt sich doch eleganter lösen.


Log in to reply