Forum: Compiler & IDEs C Pointer ohne Bindung an Datentyp


von AnddnA (Gast)


Lesenswert?

Hallo zusammen,

ich möchte einer Funktion in C einen Pointer übergeben, völlig 
unabhängig vom Typen, auf den der Pointer zeigt. Wie kann ich den 
Compiler dazu bringen bei diesem Pointer den dereferenzierten Datentypen 
nicht zu prüfen?
Der Pointer soll nach dem Dereferenzieren immer auf ein Byte zeigen, 
d.h. ich möchte der Funktion die Startadresse einer Variable eines 
beliebigen Datentyps übergeben. Auf diese Variable möchte ich byteweise 
lesend oder schreibend zugreifen.

Hier: Beitrag "Ein Datentyp für alles" wurde mein Problem 
angegangen, ich verstehe die Funktionsweise allerdings nicht. Kann mich 
jemand aufklären?

mfG. AnddnA

von Carsten (Gast)


Lesenswert?

AnddnA schrieb:
> Wie kann ich den
> Compiler dazu bringen bei diesem Pointer den dereferenzierten Datentypen
> nicht zu prüfen?

void* myPointer

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du suchst einen void-Pointer. Den musst Du allerdings zum 
Dereferenzieren nach uint8_t* (oder "unsigned char*") casten.
1
int bla(void* p)
2
{
3
  uint8_t* pp;
4
  uint8_t meins;
5
6
  pp = (uint8_t *) p;
7
8
  meins = *pp;
9
}

Gebrauch:
1
int x;
2
float y;
3
char* z;
4
5
bla(&x);
6
bla(&y);
7
bla(&z);
8
9
bla(z);

: Bearbeitet durch User
von AnddnA (Gast)


Lesenswert?

Vielen Dank für die Antworten.

Es war doch einfacher als gedacht. Mir fehlte nur der Begriff "void 
Pointer".
Mit dem void Pointer selber kann man anscheinend nicht viel machen. Man 
muss ihn, wie Rufus erwähnt hat, in einen Pointer auf einen bestimmten 
Datentyp casten. Das wollte ich noch einmal betonen, falls jemand die 
selben Fehler macht wie ich.

von Carsten (Gast)


Lesenswert?

AnddnA schrieb:
> Mit dem void Pointer selber kann man anscheinend nicht viel machen. Man
> muss ihn, wie Rufus erwähnt hat, in einen Pointer auf einen bestimmten
> Datentyp casten.

Ich würde es anders ausdrücken: Der void-Zeiger gibt einem sehr große 
Flexibilität, man muss dann aber immer genau wissen, was hinter der 
Adresse auf die er zeigt zu erwarten ist.
Schau dir mal die Implementierung des "Workerthreads" an, das ist ein 
sehr schönes Beispiel für die Anwendung des void-Zeigers.

von Markus F. (mfro)


Lesenswert?

AnddnA schrieb:
> Man
> muss ihn, wie Rufus erwähnt hat, in einen Pointer auf einen bestimmten
> Datentyp casten. Das wollte ich noch einmal betonen, falls jemand die
> selben Fehler macht wie ich.

Das muß man nicht (und sollte es auch nicht). Casts sollte man - wann 
immer möglich - vermeiden, das ist eine (meist unnötige) Fehlerquelle, 
weil man dem Compiler die Möglichkeit zur Kontrolle nimmt.

void pointer muß man nicht casten. Sie sind zuweisungskompatibel zu 
jedem beliebigen Pointer-Typ, also weist man sie sinnvollerweise zu:
1
void test(void *pv)
2
{
3
    int *pi = pv;
4
    char *pc = pv;
5
    long *pl = pv;
6
}

so geht das ganz ohne Cast, ohne Fehler, ohne Warnung. Die "zusätzliche" 
Variable stört nicht. Der Compiler optimiert sie weg, wenn sie nicht 
gebraucht wird.
Was man allerdings muß, ist - ohne Compilerhilfe - auf das richtige 
Alignment achten.

von Rolf M. (rmagnus)


Lesenswert?

AnddnA schrieb:
> Mit dem void Pointer selber kann man anscheinend nicht viel machen. Man
> muss ihn, wie Rufus erwähnt hat, in einen Pointer auf einen bestimmten
> Datentyp casten. Das wollte ich noch einmal betonen, falls jemand die
> selben Fehler macht wie ich.

Ist doch auch logisch, denn:

AnddnA schrieb:
> Auf diese Variable möchte ich byteweise lesend oder schreibend zugreifen.

Das impliziert ja einen Datentyp, nämlich einen, der ein Byte groß ist. 
void* sagt aber, dass es keinerlei Informationen darüber gibt, was sich 
dahinter verbirgt - wie man darauf zugreifen kann und nicht einmal, wie 
groß es ist. Man kann also einen void* nicht dereferenzieren, da der 
Compiler nicht weiß, wie der das, wohin er zeigt, interpretieren soll.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Markus F. schrieb:
> so geht das ganz ohne Cast, ohne Fehler, ohne Warnung.

...jaja, ohne Warnung...bis man mal auf einem System, wo Alignment eine 
Rolle spielt, damit ganz übel auf die Nase fällt.

Meine Meinung dazu sieht ganz anders aus: Man sollte void Pointer 
vermeiden und stattdessen sich Gedanken über eine bessere Struktur 
seiner Firmware machen, so daß man keine void Pointer benötigt.

W.S.

von Peter II (Gast)


Lesenswert?

W.S. schrieb:
> Meine Meinung dazu sieht ganz anders aus: Man sollte void Pointer
> vermeiden und stattdessen sich Gedanken über eine bessere Struktur
> seiner Firmware machen, so daß man keine void Pointer benötigt.

da schon malloc einen void zurück liefert, kann man wohl kaum auf void 
verzichten.

von Markus F. (mfro)


Lesenswert?

W.S. schrieb:
> Markus F. schrieb:
>> so geht das ganz ohne Cast, ohne Fehler, ohne Warnung.
>
> ...jaja, ohne Warnung...bis man mal auf einem System, wo Alignment eine
> Rolle spielt, damit ganz übel auf die Nase fällt.
>
> Meine Meinung dazu sieht ganz anders aus: Man sollte void Pointer
> vermeiden und stattdessen sich Gedanken über eine bessere Struktur
> seiner Firmware machen, so daß man keine void Pointer benötigt.
>
> W.S.

Naja, wenn man ein scharfes Messer hat, sollte man wissen, daß man sich 
dran schneiden kann.

Natürlich kann man stattdessen auch mit dem Plastiklöffel essen...

von W.S. (Gast)


Lesenswert?

Peter II schrieb:
> da schon malloc einen void zurück liefert, kann man wohl kaum auf void
> verzichten.

Soso. Bei den Abertausenden Geräten, die von mir draußen bei den Kunden 
sind, findet sich nicht ein einziger void Pointer. Also schreib keinen 
Unsinn. Man kann sehr wohl auf void Pointer verzichten und man sollte 
das auch tun. Ein Ähnliches gilt für die möglichst sparsame Verwendung 
von Typecasts.

Es nervt, hier immer wieder Beiträge von Leuten lesen zu müssen, die da 
meinen, daß sie sich auf einem µC ganz genauso benehmen können, wie es 
ihnen das Lehrbuch über C mal beigebracht hat und dabei Alles und Jedes 
auch unbedingt verwenden wollen, was die Sprachdefinition nicht 
ausdrücklich verbietet. Siehe "ich möchte einer Funktion in C einen 
Pointer übergeben, völlig unabhängig vom Typen" - fragt hier denn 
keiner, warum eigentlich der TO auf einen solchen Gedanken gekommen 
ist, wo er doch offensichtlich noch ausgesprochen ahnungslos ist: "ich 
verstehe die Funktionsweise allerdings nicht". Ja, eben. Mein rat: 
Bleibenlassen und zwar komplettiko. Stattdessen den Funktionen 
ordentliche Argumente übergeben, wo der Compiler wenigstens ne 
Restchance hat, die allegrößten Schnitzer zu erkennen und zu meckern.

W.S.

von Peter II (Gast)


Lesenswert?

W.S. schrieb:
> Soso. Bei den Abertausenden Geräten, die von mir draußen bei den Kunden
> sind, findet sich nicht ein einziger void Pointer. Also schreib keinen
> Unsinn. Man kann sehr wohl auf void Pointer verzichten und man sollte
> das auch tun.

warum sollte man auf Funktion der Standard lib verzichten? Du erfindest 
also das Rads jedes mal neu?

qsort hat void* Parameter.

Klar wenn man auf alles verzichtet, braucht man kein void* - auch bei 
ASM braucht man es nicht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

W.S. schrieb:
> Bei den Abertausenden Geräten, die von mir draußen bei den Kunden sind,
> findet sich nicht ein einziger void Pointer.

Nicht jeder muss das C-Subset verwenden, mit dem Du Dich offenbar 
eingerichtet hat.

von Sebastian V. (sebi_s)


Lesenswert?

W.S. schrieb:
> Stattdessen den Funktionen
> ordentliche Argumente übergeben, wo der Compiler wenigstens ne
> Restchance hat, die allegrößten Schnitzer zu erkennen und zu meckern.

Stimmt natürlich aber man benutzt void Pointer ja auch nicht wenn 
stattdessen ein einfacher int Pointer gereicht hätte. Meistens will man 
eine Funktion verallgemeinern für verschiedene Datentypen. Und da C 
keine Templates hat und Makros auch ziemlich gruselig sind bleibt 
eigentlich nur der void Pointer.

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.