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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren