[gelöst] Verständnisproblem bei Zeiger-Syntax
-
Diesmal habe ich eine Verstädnisfrage zur Syntax von Zeigern.
In einem Programm möchte ich ein Feld von Zahlen und ein Feld von C-Strings sortieren. Ich danke euch für Eure ZEit und Hilfe.Bei den Zahlen gehe ich laut meinem Buch wie folgt vor:
int icmp(const void * a, const void * b) { int ia = *static_cast<const int *>(a); int ib = *static_cast<const int *>(b); if(ia == ib) return 0; return ia > ib ? 1 : -1; } int main() { int ifeld[] = {100, 22, 3, 44, 6, 9, 2, 1, 8, 9}; size_t anzahl = sizeof(ifeld) / sizeof(ifeld[0]); qsort(ifeld, anzahl, sizeof(ifeld[0]), icmp); }Dabei versetehe ich die Fktn icmp wie folgt:
Ich übergebe einen Zeiger auf ein konstantes Objekt vom Typ void.
Da die Funktionen mit int-Werten arbeitet, die ich konkret verarbeiten möchte, konvertiere ich den void Zeiger in einen Zeiger auf einen konstanten Integer-Wert, den ich dann dereferenziere, um mit dem Wert zu arbeiten.
Habe ich das richtig verstanden?Falls ja, kommt hier mein Verstädnisproblem.
Das gleiche mache ich nun mit C-Strings. Laut Buch:int ccmp(const void * a, const void * b) { const char * ca = *static_cast<const char * const *>(a); const char * cb = *static_cast<const char * const *>(b); return strcmp(ca,cb); } int main() { const char * cfeld[] = {"Birgit", "Anton", "Franz", "Zenzi", "Emiliane", "Chris"}; anzahl = sizeof(cfeld)/sizeof(cfeld[0]); qsort(cfeld, anzahl, sizeof(char *), ccmp); }Ich übergebe der Fktn ccmp einen Zeiger auf ein konstantes Objekt vom Typ void.
Das Objekt (ich glaub, der Begriff ist hier eh falsch, oder?) ist nun konkret ein Zeiger auf ein konstantes Zeichen (eben const char *). Nun möchte ich doch jenen Zeiger auf const void in einen Zeiger auf const (const char
konvertieren, oder?
Wieso heißt es dannconst char * ca = *static_cast<const char * const *>(a);und nicht
const char * ca = *static_cast<const (const char *) *>(a);?
Also wenn das eine dumme Frag eist, tut es mir Leid. Aber ich verstehe es nicht...
Danke schon mal!
-
also const char * const * ist:
zeiger auf -> konstanten -> zeiger auf -> char -> was kosntant ist
(die syntax von rechts nach links lesen)
was soviel heist wie ein zeiger auf eine [konstante zeichenkette wo auch der zeiger kosntant ist]dass das nicht so gut kommt sollte auch klar sein, weil es quasi ein array von strings ist
sprich du versuchst einen string (so nennt man das "objekt") in ein array von strings zu konvertieren
achja, sizeof(char
ist immer vier, weil ein zeiger nur die addresse beeinhaltet und die ist nunmal ein int -> 4 byte
genau das gleiche kommt bei sizeof(cfeld[0]) raus, weil auch das nur ein zeiger auf char ist
-
Befremdliches Buch. qsort und static_cast? Sowas wirst Du im Einsatz niemals sehen. Warum macht der sowas?
-
Prinzipiell bezieht sich ein cv-qualifier (wie const) in einer Deklaration immer auf das, was direkt zu seiner linken steht. Also:
int const i; // int-Konstante int const *const p; // Zeigerkonstante, die auf int-Konstante zeigt int const *const *const q; // usw.Es gibt eine Ausnahme davon, und zwar dann, wenn const ganz links steht - dann bezieht es sich auf das, was direkt zu seiner rechten steht. Dementsprechend:
int const i; // ist das gleiche wie const int j;und
char const *const p; // das gleiche wie const char *const q;Das ist im ersten Augenblick etwas verwirrend, wenn man es gewohnt ist, const nach links zu schreiben. Ich empfehle, statt an "konstante Zahlen" an "Zahlenkonstanten" zu denken und const immer nach rechts zu schreiben. Das hat nebenbei auch den Vorteil, dass man sich nie mit Verwirrung um "konstante Variablen" herumschlagen muss.

-
Tonikum schrieb:
Ich übergebe einen Zeiger auf ein konstantes Objekt vom Typ void.
void enthält kein Typinformationen. Demnach kannst du keine Variable/Objekt von diesem Typen erstellen.
void ist ein besonderer Typ für Zeiger. Der Zeiger kann dann auf jedes beliebige Objekt zeigen, egal von welchem Datentypen das Objekt ist.
Um dann aber etwas mit dem Objekt, auf das der void-Zeiger zeigt, anfangen zu können, musst du zum Objekttypen hin casten, weil, wie gesagt, void keine Typinformationen hat.Tonikum schrieb:
... konvertiere ich den void Zeiger in einen Zeiger auf einen konstanten Integer-Wert, den ich dann dereferenziere, um mit dem Wert zu arbeiten.
... konvertiere ich den void Zeiger in einen konstanten Zeiger auf einen konstanten Integer-Wert, den ich dann dereferenziere, um mit dem Wert zu arbeiten.
Hast du richtig verstanden.
Ich würde in deinem Satz das Wort "konvertieren" irgendwie nicht verwenden. Das hört sich für mich so an, als ob du den void-Zeiger an sich veränderst.
Würde eher sagen, "ich interpretiere den void-Zeiger nun als einen konstanten Zeiger auf einen konstanten int-Wert."Tonikum schrieb:
Ich übergebe der Fktn ccmp einen Zeiger auf ein konstantes Objekt vom Typ void.
Du übergibst der Funktion die Adressen zweier Variablen.
Das erste const bezieht sich auf den Inhalt, auf den der Zeiger zeigt.
Das zweite const bezieht sich auf den Zeiger.
Der c++ Standard sagt nun, dass das erste const vor dem * stehen muss und das zweite const nach dem * stehen muss./* Zeiger darf nicht umgebogen werden. Zeiger darf die Variable 'i' nur lesen (read-only), und nicht modifizieren. */ int i = 7; const int* const pi = &i;
-
Vielen Dank für eure Antworten!
Skym0sh0 schrieb:
also const char * const * ist:
zeiger auf -> konstanten -> zeiger auf -> char -> was kosntant ist
(die syntax von rechts nach links lesen)
was soviel heist wie ein zeiger auf eine [konstante zeichenkette wo auch der zeiger kosntant ist]Okay, das habe ich vestanden. Wie in aler Welt komme ich darauf, dass ich das brauche? Auf der linken Seite steht ja mit "const char * ca" auch kein konstanter Zeiger da. Wieso reicht also nicht
const char * ca = *static_cast<const char * *>(a);und wieso funktioniert dann nicht auch:
const char * const ca = *static_cast<const char * const *>(a);?
Skym0sh0 schrieb:
dass das nicht so gut kommt sollte auch klar sein, weil es quasi ein array von strings ist
Wieso ist das nicht gut? o.O
volkard schrieb:
Befremdliches Buch. qsort und static_cast? Sowas wirst Du im Einsatz niemals sehen. Warum macht der sowas?
Ulrich Breymann - C++ Einführung und professionelle Programmierung
Danke sehr!
-
Du castest einen Zeiger auf void const in einen Zeiger auf etwas anderes. cv-Qualifier wirst du ohne const_cast nicht los, also muss dieses andere auch const sein.
Im Übrigen möchte ich anmerken, dass das in professionellem C++ etwa so aussähe:
#include <algorithm> #include <cstddef> #include <cstring> #include <string> template<typename T, std::size_t N> std::size_t array_size(T(&)[N]) { return N; } bool c_strless(char const *p, char const *q) { return strcmp(p, q) < 0; } int main() { std::string sfeld[] = { "Birgit", "Anton", "Franz", "Zenzi", "Emiliane", "Chris" }; std::sort(sfeld, sfeld + array_size(sfeld)); // Gelegentlich vielleicht so: const char *cfeld[] = { "Birgit", "Anton", "Franz", "Zenzi", "Emiliane", "Chris" }; std::sort(cfeld, cfeld + array_size(cfeld), c_strless); }Das Buch, aus dem du deinen Code hast, wäre wahrscheinlich besser mit "C mit Klassen: Einführung in völlig veraltete Praktiken" betitelt. Bis auf die C++-Casts ist das alles reines C.
-
Danke für die Mühe Seldon!
Ich glaub, ich werde das nie richtig können.
Mit welchen Büchern habt ihr denn C++ gelernt?
-
C++ Primer ist eigentlich ganz gut für den Einstieg.
Falls du schon ein wenig Programmiererfahrung hast, dann würde ich dir zum The C++ Programming Language von Bjarne Stroustrup raten.