offsetof Makro mit Zeiger auf Element in Struct

Gast #2121376
Lesenswert?
• ▲
▼
Hallo zusammen,
ich programmiere nicht mit dem gcc sondern mit MPLab und dem Hi-Tech 
Pic16 C-Compiler. Aber ich denke und hoffe, dass ihr mir weiterhelfen 
könnt. Ich habe ein Struct wie folgt definiert:

   struct DATA{
      short value1;
      short value2;
      short value3;
      short value4;
   } Werte;

nun kann ich ja über das Makro offsetof die Position eines Elements im 
Struct herausfinden. Dies funktioniert auch mit folgendem Quelltext:

   offsetof(struct DATA, value2);

Nun stellen die Werte value1, value2,... unterschiedliche Werte dar, 
welche in einem Menü verändert werden können. Dazu gibt es einen Zeiger 
auf den zum aktuell ausgewählten Menüpunkt zugehörigen Wert. Also der 
Wert welcher im ausgewählten Menüpunkt geändert werden kann wird über 
einen Zeiger angesprochen bspw.:

   short *pointer = &Werte.value2;

in der Menüfunktion wird jetzt der Wert des Pointers verändert. Nun 
möchte ich die Position im Struct des Wertes herausfinden, auf welchen 
der Pointer zeigt. Dazu habe ich folgendes ausprobiert nur leider 
funktioniert das nicht:

   offsetof(struct DATA, *pointer);

Der Compiler bringt mir die Fehlermeldung "Zeiger erforderlich"

Kann mir hier bitte jemand weiterhelfen??? Habe ich einen Denkfehler 
oder geht das einfach nicht? Gibt es einen anderen Weg???

Vielen Dank schon im Vorraus!!!
Flo
Gast #2121409
Lesenswert?
• ▲
▼
Das scheint eher eine Aufgabe für ein Array statt ein struct zu sein.

Fragender schrieb:
>     offsetof(struct DATA, *pointer);
>
> Der Compiler bringt mir die Fehlermeldung "Zeiger erforderlich"

Das zweite Argument für das Makro muss der Name eines Elements sein. So 
geht das nicht.

Um nur die Differenz zweier Zeiger zu erhalten, muss man sie voneinander 
abziehen (so weit, so offensichtlich).  Allerdings erhält man die 
Differenz in Einheiten der Datenobjekte, auf die gezeigt wird. Wenn die 
Differenz in Bytes gewünscht wird, muss man beide Zeiger nach char* 
casten.


Mit Arrays ist alles viel einfacher:
1
short Werte[4];
2

3
short *pointer = &Werte[1];
4

5
int index = pointer - Werte;
Gast #2121608
Lesenswert?
• ▲
▼
Vielen Dank!

Habe aber leider nicht gesagt, dass im Struct nicht nur shorts, sondern 
auch andere Datentypen sind. Deshalb doch leider Struct. Mit einem Array 
habe ich es zuvor implementiert und das hat auch funktioniert. Dann 
müsste es doch aber folgendermaßen funktionieren:

    unsigned char *offset = (unsigned char)pointer - &(unsigned 
char)Werte

Flo
Gast #2121744
Lesenswert?
• ▲
▼
Fragender schrieb:
> Habe aber leider nicht gesagt, dass im Struct nicht nur shorts, sondern
> auch andere Datentypen sind. Deshalb doch leider Struct. Mit einem Array
> habe ich es zuvor implementiert und das hat auch funktioniert.

Man kann ein Array auch als Element von einem struct definieren…

Fragender schrieb:
> Dann
> müsste es doch aber folgendermaßen funktionieren:
>
>     unsigned char *offset = (unsigned char)pointer - &(unsigned
> char)Werte

Das funktioniert überhaupt nicht.

Und ich habe in meinem Beispiel die Variable nicht offset, sondern index 
benannt — aus dem Grund, dass es den Index ins Array ergibt und nicht 
den Byte-Offset. Wenn du den willst, musst du den Index einfach mit der 
Elementgröße, hier "sizeof (short)", multiplizieren.
Gast #2121749
Lesenswert?
• ▲
▼
Verwende ein Pointer als pointer, und nicht deren Inhalt !!!.
Dein falscher Code:
   offsetof(struct DATA, *pointer);

sollte lauten
   offsetof(struct DATA,  pointer);


Wenn du überlegst warum, wirst du warscheinlich auch erraten wieso.
Gast #2121752
Lesenswert?
• ▲
▼
Chris schrieb:
> Verwende ein Pointer als pointer, und nicht deren Inhalt !!!.
> Dein falscher Code:
>    offsetof(struct DATA, *pointer);
>
> sollte lauten
>    offsetof(struct DATA,  pointer);

Das funktioniert genauso wenig, pointer ist kein Name eines Elements von 
struct DATA.
Gast #2121762
Lesenswert?
• ▲
▼
Stimmt, sorry.
Wenn pointer ein member von Werte ist, kannst du ptrdiff anstelle von 
offsetoff verwenden, sofern definiert. Ansonsten einfach
#define ptrdiff(x,y) (((unsigned int)&x)-(unsigned int)&y)

Ansonsten, geht nicht.
Gast #2123687
Lesenswert?
• ▲
▼
Dass das ganze merkwürdig ausschaut und weshalb man soetwas eigentlich 
nicht verwenden sollte lasse ich mir gerne auch erklären, verstehe zwar 
nicht warum aber naja. In meinem Fall macht es aber Sinn, da es weniger 
Speicherplatz benötigt (habs getestet) und auch einfacher erweiterbar 
ist!!!

Habe das Problem übrigens folgendermaßen gelöst und es funktioniert:

unsigned char offset = (unsigned char*)pointer - (unsigned char*)&Werte

Vielen Dank an alle!!!
Flo

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.