Forum: Compiler & IDEs Struktur definieren aus pointer definieren


von Jens D. (jens) Benutzerseite


Lesenswert?

Hallo,

ich versuche gerade aus einem Pointer eine Struktur zu definieren.
1
typedef struct {
2
 ....
3
}S_foo;
4
5
S_foo struct_foo;
6
7
/* wird durch Funktionen geschoben und teils für Funktionspointer missbraucht) */
8
int bar = (uint32_t)struct_foo;

Nun möchte ich an anderer Stelle aus "bar" wieder die Struktur 
erstellen.
Leider lässt er das caten nicht zu.

Error[Pe144]: a value of type "uint32_t" cannot be used to initialize an 
entity of type "S_foo *" ...main.c 153

Was fehlt? Oder besser, wie wird es richtig gemacht?

Danke

von S. R. (svenska)


Lesenswert?

Du kannst die Struct nicht in einen uint32_t stopfen, denn sie ist 
größer. Du kannst aber die Adresse der Struct in den uint32_t (besser: 
uintptr_t) stopfen:
1
uintptr_t bar = (uintptr_t)&S_foo;

von Jens D. (jens) Benutzerseite


Lesenswert?

struct_foo ist der Pointer, die Adressen passen auch.

Problem war nur das zurück casten.

Im Grunde ganz einfach
1
   S_foo *foobar = (S_FOO*)bar;

von Tsca k (Gast)


Lesenswert?

>typedef struct {
> ....
>}S_foo;
>
>S_foo struct_foo;
>....
>
>struct_foo ist der Pointer, die Adressen passen auch.

Deine Gedanken sind wirr! Dieses Problem solltest Du beheben.

von Eric B. (beric)


Lesenswert?

1
#include <stdint.h>
2
3
typedef struct 
4
{ ...
5
} Foo;
6
7
Foo the_data;
8
9
int main()
10
{
11
  Foo * foo_pointer;
12
  uintptr_t foo_fighter;
13
14
  foo_pointer = &the_data;                  // get pointer
15
  foo_fighter = (uintptr_t) foo_pointer;    // convert to integer...
16
  foo_pointer = (Foo *) (foo_fighter + 32); // ...and back. Dangerous!
17
18
  return 0;
19
}
Compiliert ohne Probleme.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Das man sich mit C syntaxfehlerfrei die allerschönsten Probleme 
herbeiprogrammieren kann, muß eigentlich nicht erneut bewiesen werden.

Oliver

von Tom (Gast)


Lesenswert?

Die Welt wäre besser, wenn Compiler für jeden Typecast 5€ Gebühr und 
eine halbseitige schriftliche Begründung der Notwendigkeit verlangen 
würden.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jens D. schrieb:
> Error[Pe144]: a value of type "uint32_t" cannot be used to initialize an
> entity of type "S_foo *" ...main.c 153

Nenne mir einen Grund, warum Du dafür eine 32Bit-Variable missbrauchen 
willst.

Schreib doch statt:
int bar = (uint32_t)struct_foo;
neu:
S_foo * bar = &struct_foo;

und zurück:
S_foo * ptr = bar;

Das läuft ohne Casts und ohne Warnings.

Jens D. schrieb:
> /* wird durch Funktionen geschoben und teils für Funktionspointer
> missbraucht) */

Dann schieb es richtig durch die Funktionen und nicht per uint32_t. Das 
ist höchst unportabel. Soll das eigentlich auf einem 8-Bit-µC oder 
32-Bit-Rechner oder gar 64-Bit-Rechner funktionieren?

Eric B. schrieb:
> foo_pointer = (Foo *) (foo_fighter + 32);

Erkläre mir bitte den Offset von +32. Der erschließt sich mir nicht.

: Bearbeitet durch Moderator
von Oliver S. (oliverso)


Lesenswert?

Frank M. schrieb:
> Erkläre mir bitte den Offset von +32. Der erschließt sich mir nicht.

Er hätte auch 42 hinschreiben können. Hauptsache, es kompiliert ohne 
Fehler ;)

Oliver

von Eric B. (beric)


Lesenswert?

Frank M. schrieb:
> Eric B. schrieb:
>> foo_pointer = (Foo *) (foo_fighter + 32);
>
> Erkläre mir bitte den Offset von +32. Der erschließt sich mir nicht.

Ich hätte auch 42 hinschreiben können (hi Oliver ;-)), oder 27, oder gar 
nix.
Es war nur als Beispiel gedacht...

von Walter S. (avatar)


Lesenswert?

Frank M. schrieb:
> Nenne mir einen Grund, warum Du dafür eine 32Bit-Variable missbrauchen
> willst.

na Du warst doch auch Mal jung Frank

und ich auch!

Vor 2 Jahren musste ich ein Programm auf einen 64-Bit Mac übertragen das 
ich vor über 25 Jahren geschrieben habe.
Und damals hatte ich an einer Stelle genau diesen Fehler gemacht den 
Jens gerade machen will ...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Walter S. schrieb:
> na Du warst doch auch Mal jung Frank

Stimmt :-)

> Vor 2 Jahren musste ich ein Programm auf einen 64-Bit Mac übertragen das
> ich vor über 25 Jahren geschrieben habe.
> Und damals hatte ich an einer Stelle genau diesen Fehler gemacht den
> Jens gerade machen will ...

Eine portable Methode, verschiedene Datentypen durch eine Funktion zu 
schieben, wäre eine union. Man setzt den entsprechenden Member in der 
union und evtl. ein Flag, von welchem Typ die übergebenen Daten sind 
(wenn die Funktion das wissen muss) und übergibt dann den Pointer auf 
die union. Die Funktion kann diese Daten dann evtl. weitergeben oder 
selbst verarbeiten - unter Zuhilfenahme des angegebenen Typs in der 
union.

So kann man Daten verschiedenen Typs mit einer Breite von 8, 16, 32 und 
64 Bit portabel übergeben, ohne dass es später bei einer Portierung auf 
eine andere CPU kracht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.