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
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.
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.
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
voidtest(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.
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.
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.
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.
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...
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.
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.
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.
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.