Zeiger auf Struktur

Gast #2788487
Lesenswert?

Hallo,

ich schlag mich grad mal wieder mit einem Zeiger Problem herum.

Ich habe einen globalen Zeiger auf eine Struktur. Diese Struktur hat 
unter anderem als Member einen Zeiger auf Daten:
1
typedef struct{
2
  //member;
3
  //nochnmember;
4
  uint8 *data;
5
}my_struct_t;
6

7
my_struct_t *my_struct_ptr;

Nun würde ich gerne in einer Funktion auf den Datenteil dieser Struktur 
zugreifen.

Folgendes funktioniert:
1
void foo(void)
2
{
3
  uint8 *local_ptr;
4
  local_ptr = my_struct_ptr->data;
5

6
  local_ptr[0] = ...;
7
  local_ptr[x] = ...;
8
}

Probier ichs ohne Umweg über den lokalen Zeiger
1
  my_struct_ptr->data[0] = ...;

Meckert mirs der Compiler an.
"expression must be a pointer to a complete object type"

Damit kann ich nichts anfangen. Bin grad bisl ratlos, kann mir jemand 
weiterhelfen?

Viele Grüße,
Rudi
#2788500
Lesenswert?

Rudi schrieb:

>
1
>   my_struct_ptr->data[0] = ...;
2
>
>
> Meckert mirs der Compiler an.
> "expression must be a pointer to a complete object type"

der SChlüssel ist an dieser Stelle die Phrase "complete object type". An 
der Stelle an der du das machst, weiß der Compiler nicht, wie ein 
my_struct_t aussieht.
Wahrscheinlich hast du nur vergessen, das Header File zu inkludieren, in 
dem die struct definiert ist.
#2788553
Lesenswert?

Rudi schrieb:
> Hm garned bedacht. Macht aber Sinn, immerhin kennt er ja dann die Größe
> des Elements nicht, sodass er spätestens beim Zugriff mitells [0],
> [1]... überfordert wäre, richtig?


richtig.
In die Indexberechnung geht ja logischerweise auch immer die sizeof des 
Typs ein um zu Berechnen, wieviele Bytes zwischen Anfang des Arrays und 
dem interessierenden Arrayelement liegen.
#2788556
Lesenswert?

Rudi schrieb:
> Kann man das dann irgendwie umcasten?

natürlich kann man umcasten.
Allerdings solltest du dich fragen, ob da prinzipiell der void* 
überhaupt eine gute Idee war. Wenn du sowieso den Datentyp kennst auf 
den du casten willst, warum steht dann der nicht gleich da drinnen?

Es gibt natürlich Fälle, an denen man bewusst einen void* einsetzt. Zb 
wenn ein Modul eine Strukturobjekt rausgeben muss und nicht haben will, 
dass sich derjenige der das Objekt benutzt, an den Daten vergreift. Der 
void* ist dann mehr oder weniger ein 'Finger weg! An diesen Daten hast 
du nichts zu suchen'.
Gast #2788560
Lesenswert?

Weil der Typ von einer Lib, genauer gesagt dem LwIP Stack, vorgegeben 
ist.

Dort gibt es die Struktur pbuf, die als Buffer für ein- und ausgehende 
Datenströme dient. Und die zeigt leider auf void.

Wie müsste denn der Cast aussehen?
#2788564
Lesenswert?

Rudi schrieb:
> Weil der Typ von einer Lib, genauer gesagt dem LwIP Stack, vorgegeben
> ist.
>
> Dort gibt es die Struktur pbuf, die als Buffer für ein- und ausgehende
> Datenströme dient. Und die zeigt leider auf void.

Eigenartig.
Sicher, dass das so gedacht ist, dass du auf diese Werte zugreifen 
darfst?

(Vielleicht wollten sie aber auch den Aufrufer auch nur dazu zwingen, 
dass er ein wenig darüber nachdenkt, was das eigentlich für Daten sind, 
die er da bekommt: int, float, double, bytes, ...
üblich ist es allerdings nicht. Solche Buffer werden normalerweise als 
Bytes angesehen - also 'unsigned char' Arrays.


>
> Wie müsste denn der Cast aussehen?

Na ja, eben den Pointer entsprechend umcasten

    ((uint8_t*)(my_struct_ptr->data))[0]

sieht ein wenig seltsam aus, daher wäre wohl der Weg über eine 
Zwischenvariable der syntaktisch lesbarere. Der Compiler schmeisst die 
Variable ja sowieso wieder raus.
Gast #2788571
Lesenswert?

Karl Heinz Buchegger schrieb:
> Eigenartig.
> Sicher, dass das so gedacht ist, dass du auf diese Werte zugreifen
> darfst?

Laut der (leider sehr dürftigen) Doku im Internet und den Beispielen die 
ich gefunden habe wird das durchaus so gemacht.

Die allokierte Buffergröße wird auch in der Struktur abgelegt, somit ist 
es wohl dem Benutzer überlassen den Zugriff ordentlich zu regeln.

Aber ich muss sagen, der LwIP Stack ist nicht gerade ein Musterbeispiel 
für lesbaren Code...
#2788576
Lesenswert?

Rudi schrieb:
> Karl Heinz Buchegger schrieb:
>> Eigenartig.
>> Sicher, dass das so gedacht ist, dass du auf diese Werte zugreifen
>> darfst?
>
> Laut der (leider sehr dürftigen) Doku im Internet und den Beispielen die
> ich gefunden habe wird das durchaus so gemacht.
>
> Die allokierte Buffergröße wird auch in der Struktur abgelegt, somit ist
> es wohl dem Benutzer überlassen den Zugriff ordentlich zu regeln.

:-)
Womit sich dann allerdings die Frage erhebt, wie denn die Buffergröße 
angegeben ist. Sind das Bytes, Floats, andere Objektgrößen, Äpfel, 
Birnen ...
:-)

(Ist jetzt keine Kritik an dir. Soll dir nur zeigen, dass an dieser 
Stelle der void* nicht sehr logisch ist. WEnn ich schon die Buffergröße 
(in Bytes) in der Struktur habe, dann wäre es logisch auch den Pointer 
als Byte-Pointer anzulegen. Dann passen beide in den Einheiten zusammen.

Ändert nichts daran, dass man des öfteren sowieso umcasten muss. Aber 
dann muss man ja auch die Längenangabe umrechnen und kann das so gesehen 
ohnehin nicht verpassen.
Gast #2788582
Lesenswert?

Das Ganze ist wohl einfach "historisch gewachsen" und generell sehr 
undurchsichtig.

Die Puffer sind außerdem einfach verkettet und speichern noch ihr 
nächstes Element, die Gesamtgröße der Kette und die Größe des jeweiligen 
Segments. Alle Angaben in Bytes.
Und halt das Datenelement als void*.

Aber das geht ja noch, richtig dreckig sind erst die Präprozessor 
Spielereien...
Gast #2789543
Lesenswert?

Karl Heinz Buchegger schrieb:
> (Ist jetzt keine Kritik an dir. Soll dir nur zeigen, dass an dieser
> Stelle der void* nicht sehr logisch ist.

Warum nicht? Ist auch nicht anders, als auf dem PC. Wenn ich da mit 
read() aus einem Socket lese, übergebe ich auch einen void* und einen 
size_t, was er dann nutzt, um seine Daten reinzuschreiben.
Es geht um einen Puffer mit (für das API) völlig unbekanntem Inhalt. Da 
erscheint mir ein void* eigentlich recht passend. malloc() gibt ja auch 
keinen Zeiger auf char zurück, nur weil ich ihm als Parameter die 
gewünschte Größe in Bytes angebe.

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