int* nach void*
-
1. Wofür experimentierst du in C++ mit solch hässlichem Code herum?
2. Ungenügende Compilerfehlermeldung. Wenn es eine Fehlermeldung gibt, zeig sie uns doch bitte.
3. Verwende bitte cpp Tags für C++ Code.
4. Einen doppeltenvoid
-Zeiger gibt es nicht. Der Cast am Ende ist zudem falsch, du möchtest schliesslich zurück auf einenint**
. Also korrekt wäre:int main() { void* pv; int* pint; int i; pint = &i; pv = &pint; // Gibt einen int** zurück, wird als void* gespeichert. **static_cast<int**>(pv) = 3378; std::cout << i <<std::endl; return 0; }
Grüssli
-
Dravere schrieb:
Also korrekt wäre:
int main() { void* pv; int* pint; int i; pint = &i; pv = &pint; // Gibt einen int** zurück, wird als void* gespeichert. **static_cast<int**>(pv) = 3378; std::cout << i <<std::endl; return 0; }
Wozu hierbei Zeiger auf Zeiger?
Korrekt ist:#include <iostream> int main() { int i; void* pv = &i; *static_cast<int*>(pv) = 3378; std::cout << i <<std::endl; return 0; }
:xmas1:
Grüssli
-
Hallo zusammen
,
vielen Dank erstmal für Eure Beiträge, entschuldige wenn ich einige mit meinen Fragen ein wenig genervt habe. Ich glaube es ist einfach von der Natur aus so, dass Frauen Dinge mehr hinterfragen, weshalb ich mich ein wenig mehr mit dem Thema void* beschäftige.Ich habe aus dem Internet ein Stück Lernmaterial gefunden, dem glaube ich ein Fehler unterläuft. Vielleicht könnt Ihr mir das bestätigen oder gar mich korriegeren, wenn ich nen Denkfehler fabriziert habe. Danke im Voraus.
Folgender Code:
#include <iostream> int main() { int intValue = 1; int *intPointer = & intValue; // zeigt auf intValue void *voidPointer; voidPointer = intPointer; // voidPointer zeigt auf intPointer
Meiner Ansicht nach ist der 2. Kommentar nicht richtig, zeigt denn voidPointer nicht auf intValue? Der Verlauf geht zwar ÜBER intPointer, zeigen tut aber voidPointer doch auf intValue, oder?
Grüße aus Rheinland,
Ratna
PS. Kann man eigentlich im Beitrag Datei anhängen? Ich habe bei Zeigeraufgaben immer Zeichnungen gemacht, zu diesem Code hab ich auch eine gemacht, leider kann man scheinbar keine Datei anhängen.
-
Richtig, voidPointer zeigt auf intValue.
'intPointer' repräsentiert die Adresse von intValue, und da du voidPointer auf diese Adresse zeigen lässt ...
MfG
-
hustbaer schrieb:
Hier reinterpret_cast zu empfehlen ist IMO grob falsch.
Angebracht wäre ein static_cast.Argh! Natürlich,
static_cast
reicht ja beivoid*
. Dabei habe ich das gerade eben noch verwendet...muss_klausur_bestehen schrieb:
PS. Kann man eigentlich im Beitrag Datei anhängen? Ich habe bei Zeigeraufgaben immer Zeichnungen gemacht, zu diesem Code hab ich auch eine gemacht, leider kann man scheinbar keine Datei anhängen.
Nein, das ist hier nicht möglich. Du kannst aber die Datei irgendwo hochladen und verlinken.
Wobei bei Code-Zeichnungen die Chance natürlich grösser ist, dass sich jemand Zeit dafür nimmt. Besonders, wenn man sieht, dass sich jemand Mühe gegeben hat...
-
muss_klausur_bestehen schrieb:
Ich glaube es ist einfach von der Natur aus so, dass Frauen Dinge mehr hinterfragen, weshalb ich mich ein wenig mehr mit dem Thema void* beschäftige.
Ist einfach unglaublich, früher haben die Männern die Frauen diskriminiert, heute ist es umgekehrt ...
Es ist schön, dass man die Sache hinterfragt und sich damit beschäftigt. Die Sache ist einfach nur so, dass manvoid*
in C++ so gut wie gar nie benötigt.void*
ist extrem gefährlich, da es ein Zeiger ohne Typ ist. Man vernichtet damit jegliche Typsicherheit, welche in C++ sehr wertvoll ist. Jeglichervoid
-Zeiger ist eine extreme Gefahr in einem C++ Programm und sollte daher unbedingt vermieden werden, ausser man weiss ganz genau, was man macht.void*
stammt hauptsächlich aus C, wo man keine Templates hat und dadurch, wenn man über eine Funktion mehrere Typen durchbringen möchte, aufvoid*
zurückgreifen musste.// Als typisches Beispiel, qsort aus C: void qsort(void* base, size_t num, size_t size, int (*comparator)(void const*, void const*));
In C++ hat man genau für solche Dinge die C++ Templates:
template<typename TypeT> void qsort(TypeT* base, size_t num, int (*comparator)(TypeT const*, TypeT const*));
Dadurch wird für jeden Typ vom Kompiler eine entsprechende Funktion automatisch generiert und die Typsicherheit ist völlig gewährleistet.
Ich möchte auch darauf hinweisen, dass dies nur als Beispiel gedacht ist. In C++ kann man dass sogar noch deutlich schöner mit den Templates lösen, aber ich wollte, dass man noch eine Ähnlichkeit wahrnehmen kannWieso der ganze Vortrag?
Es ist schön und gut, dass man sich mitvoid*
auskennt, aber man sollte sich bewusst sein, dassvoid*
in 99,99% der Fälle unter C++ der falsche Weg ist.Grüssli
-
Dravere schrieb:
4. Einen doppelten
void
-Zeiger gibt es nicht.Glaub ich nicht!
"void**" frisst jeder Compiler. Hab den Standard gerade nicht hier, würde mich aber SEHR wundern wenn da drin stehen würde dass das nicht OK sein sollte. Wieso auch, sehe keinen Grund warum das nicht erlaubt sein sollte.
-
hustbaer schrieb:
Dravere schrieb:
4. Einen doppelten
void
-Zeiger gibt es nicht.Glaub ich nicht!
Ist auch korrekt, dies nicht zu glauben, habe gerade nachgeschaut. Es gibt anscheinend von der Standardbibliothek selbst eine Verwendung in den Streamklassen.
Aber der Sinn entzieht sich mir. Jeglicher Zeiger (auch Funktionszeiger) lässt sich auf einen
void*
abbilden. Das ist so im Standard definiert. Daher ist einvoid**
nur möglich, als Zeiger auf einenvoid*
, alles andere ist nicht erlaubt, was auch irgendwo Sinn macht....
Und mir kam gerade eine Idee, wieso das auch Sinn macht. Ach ich trottel ... ein
void*
hat im Gegensatz zu einemvoid
natürlich einen Speicherbereich. *Kopf -> Tisch / Tastatur*
Man denke daher nur zum Beispiel an folgendes Beispiel:int (*func)(char, double) = 0; // Nur als Beispiel. void** p = new void*[20]; // 20 oder x oder y was auch immer. *p = func; ++p; *p = 0; // usw. delete[] p;
Allerdings ist mir sowas in den x Jahren noch nicht begegnet in C++.
Grüssli
-
Ich glaube mich zu erinnern dass der Standard nicht "erlaubt" Funktionszeiger zu Datenzeigern (inklusive void*) zu casten (bzw. es nicht garantiert, kann sein dass "implementation defined" dasteht oder sowas). Was *sehr* schade ist, da man so einige Lowlevel-Dinge nicht portabel programmieren kann.
-
hustbaer schrieb:
Ich glaube mich zu erinnern dass der Standard nicht "erlaubt" Funktionszeiger zu Datenzeigern (inklusive void*) zu casten (bzw. es nicht garantiert, kann sein dass "implementation defined" dasteht oder sowas). Was *sehr* schade ist, da man so einige Lowlevel-Dinge nicht portabel programmieren kann.
Ich weiss nur, dass es mit dem MSVC funktioniert und habe auch nie gegenteiliges gelernt. Nur bei Zeiger zu Membern weiss ich, dass man sie nicht einem
void*
zuweisen darf. Dort hat es allerdings irgendeinen Grund wegen Typsicherheit.
Aber keine Ahnung, ich weiss es schlicht und einfach nicht und brauche solche Konvertierungen auch nichtGrüssli
-
Dravere schrieb:
Allerdings ist mir sowas in den x Jahren noch nicht begegnet in C++.
Ich hatte einmal eine Speicherverwaltungsklasse geschrieben, die Adressen speichern sollte. Anfangs hab ich das noch voll im C-Style gemacht, also Zeiger auf dynamisch allokiertes
void*
-Array. Später hab ich dann die STL mit eigenem Allocator verwendet, was vieles vereinfacht und denvoid**
unnötig gemacht hat.
-
muss_klausur_bestehen schrieb:
...Ich glaube es ist einfach von der Natur aus so, dass Frauen Dinge mehr hinterfragen, weshalb ich mich ein wenig mehr mit dem Thema void* beschäftige....
Stimmt ja - wir Männer haben uns noch nie Gedanken über void* gemacht!
Wer ist eigentlich dieser Herr "Natur"? Und warum hat er aus Frauen die besseren void*-Versteher gemacht? ... alles Fragen, die ich als Mann natürlich gar nicht stellen darf...
Gruß,
Simon2.
-
Dravere schrieb:
hustbaer schrieb:
Ich glaube mich zu erinnern dass der Standard nicht "erlaubt" Funktionszeiger zu Datenzeigern (inklusive void*) zu casten (bzw. es nicht garantiert, kann sein dass "implementation defined" dasteht oder sowas). Was *sehr* schade ist, da man so einige Lowlevel-Dinge nicht portabel programmieren kann.
Ich weiss nur, dass es mit dem MSVC funktioniert und habe auch nie gegenteiliges gelernt. Nur bei Zeiger zu Membern weiss ich, dass man sie nicht einem
void*
zuweisen darf. Dort hat es allerdings irgendeinen Grund wegen Typsicherheit.
Aber keine Ahnung, ich weiss es schlicht und einfach nicht und brauche solche Konvertierungen auch nichtGrüssli
Ich weiss auch dass es geht, und zwar mit allen Compilern die ich kenne. Was Member-Pointer angeht, die kann man IIRC garnicht verlässlich casten, nichtmal zu anderen Member-Pointern. Bzw. nur sehr eingeschränkt.
-
mammamia;
-
mammamia;