Der Sternoperator in C
-
Hallo ich habe eine Frage bezüglich des Sternoperator’s in C, also ich weiß man kann damit definieren das eine variable als Zeiger deklariert werden soll.
Jetzt habe ich aber auch Codebeispiele gesehen wo an einer Variable 2 sogar 3 Sternoperatoren stehen, hat das auch was mit Zeigern zu tun? Oder hat das dann eine andere bedeutung?
-
Bei der Definition steht "T* x;" für "x ist ein Zeiger auf T" - dabei kann T selber wieder ein Zeiger sein - damit erhältst du dann Doppel- (T**x - Zeiger auf Zeiger auf T) und Dreifach-Zeiger.
(außerdem dient der Stern noch zur Dereferenzierung eines Zeigers (*x ist der Wert, auf den x zeigt - auch mehrfach hintereinander erlaubt) - und zur Multiplikation (dann aber nur alleinstehend und von zwei Werten umgeben))
-
Danke, ich sehe das kann später ganz schön Kompliziert werden mit den Zeigern.
-
Falls es dich beruhigt - mehr als zwei Zeigerebenen sind nach meiner Erfahrung eher selten (Doppelzeiger kommen schon regelmäßig vor, z.B. für String-Arrays oder zur Übergabe von Zeigervariablen "by-ref"*).
* an die "Experten": Ich weiß, daß C keine Referenzen kennt - also bitte jetzt keine Spitzfindigkeiten.
-
CStoll schrieb:
Ich weiß, daß C keine Referenzen kennt...
nein, du glaubst.
-
lord_fritte schrieb:
Jetzt habe ich aber auch Codebeispiele gesehen wo an einer Variable 2 sogar 3 Sternoperatoren stehen, hat das auch was mit Zeigern zu tun? Oder hat das dann eine andere bedeutung?
CStoll schrieb:
Bei der Definition steht "T* x;" für "x ist ein Zeiger auf T" - dabei kann T selber wieder ein Zeiger sein - damit erhältst du dann Doppel- (T**x - Zeiger auf Zeiger auf T) und Dreifach-Zeiger.
(außerdem dient der Stern noch zur Dereferenzierung eines Zeigers (*x ist der Wert, auf den x zeigt - auch mehrfach hintereinander erlaubt) - und zur Multiplikation (dann aber nur alleinstehend und von zwei Werten umgeben))
Darf ich da bitte noch mal nachhaken ...
Mir stellte sich kuerzlich die gleiche Frage, aber bevor ich mich entschieden hatte, ob ich diese Frage denn nun hier posten sollte oder vielleicht alleine die Antwort finde, ist mir dann lord_fritte zuvorgekommen ...
Also ich habe hier mal ein konkretes Beispiel aus einer Reference:
Syntax int scr_dump (const char *filename);
Und ein Stueck tiefer wird die vorstehende Syntax dann ah Hand eines Beispiels erlaeutert. Und da steht nun:
scr_dump("/tmp/virtual.dump");
Ich selbst hatte das jetzt zunaechst in meinen jugendlichen Leichtsinn so interpretiert, dass ich beim Aufruf der Funktion einen Parameter vom Typ "const char" als Referenze auf eine Variable namens "filename" uebergeben muss.
Aber wieso, weshalb und weswegen wird jetzt in der Erlaeuterung "/tmp/virtual.dump" uebergeben? Das ist doch einfach nur ein String, oder ...?
Wie passt das jetzt mit Deiner Erlaeuterung zusammen, wo ist da jetzt welcher Zeiger auf was?
Gruss
Guenther
-
Es wird ein Parameter vom Typ "const char*" (Zeiger auf ein konstantes char(Array)) übergeben - und Strings werden in C als char-Arrays umgesetzt.
Zeiger unterstützen neben dem "einfachen" Dereferenzieren auch Adress-Arithmetik - unter der Annahme, daß der "Zeiger auf T" auf den Anfang eines T-Arrays zeigt, kannst du dich mit ihm durch dieses Array hangeln (allerdings ohne irgendwelche interne Sicherheitsmaßnahmen). Und ein Array wird in fast allen Zusammenhängen zerlegt zu einem Zeiger auf sein erstes Element.
-
CStoll schrieb:
Es wird ein Parameter vom Typ "const char*" (Zeiger auf ein konstantes char(Array)) übergeben - und Strings werden in C als char-Arrays umgesetzt.
Zeiger unterstützen neben dem "einfachen" Dereferenzieren auch Adress-Arithmetik - unter der Annahme, daß der "Zeiger auf T" auf den Anfang eines T-Arrays zeigt, kannst du dich mit ihm durch dieses Array hangeln (allerdings ohne irgendwelche interne Sicherheitsmaßnahmen). Und ein Array wird in fast allen Zusammenhängen zerlegt zu einem Zeiger auf sein erstes Element.
Ich denke, jetzt habe ich es verstanden ...
Ich drueck's mal mit meinen Worten aus: Weil es in C - anderes als in C++ - ja den Typ String nicht gibt, ist alles was dort nach String ausschaut in Wirklichkeit ein char-Array. Und eben deshalb kann ich das 'Teil' nicht direkt ansprechen sondern gehe den 'Umweg' ueber den Zeiger auf eben dieses Array.
Ja, das leuchtet ein ...
-
gboelter schrieb:
Ich drueck's mal mit meinen Worten aus: Weil es in C - anderes als in C++ - ja den Typ String nicht gibt, ist alles was dort nach String ausschaut in Wirklichkeit ein char-Array. Und eben deshalb kann ich das 'Teil' nicht direkt ansprechen sondern gehe den 'Umweg' ueber den Zeiger auf eben dieses Array.
naja, nicht ganz. der zugriff über einen char* ist eigentlich kein umweg, sondern direkter geht es nicht. 'std::string' in C++ ist kein eingebauter datentyp (wie char*), sondern ein haufen code, um char-pointers vorm benutzer zu verstecken und den umgang mit zeichenketten so ausehen zu lassen, als wären es native datentypen (z.b. indem operator-overloading verwendet wird, =, +, usw).
intern ist ein string immer noch eine folge von 'chars' und um darauf zuzugreifen, nimmt man eben char*
-
Apeman schrieb:
naja, nicht ganz. der zugriff über einen char* ist eigentlich kein umweg, sondern direkter geht es nicht. 'std::string' in C++ ist kein eingebauter datentyp (wie char*), sondern ein haufen code, um char-pointers vorm benutzer zu verstecken und den umgang mit zeichenketten so ausehen zu lassen, als wären es native datentypen (z.b. indem operator-overloading verwendet wird, =, +, usw).
intern ist ein string immer noch eine folge von 'chars' und um darauf zuzugreifen, nimmt man eben char*
Der faellt mir doch gleich mal wieder der Spruch vom alten Konfuzius ein, der ja angeblich gesagt haben soll: "Je mehr ich weiss, um so mehr weiss ich, dass ich nichts weiss!"
Na ja, ich hab' ja noch ein paar Jahre Zeit das alles zu begreifen ...
-
gboelter schrieb:
Der faellt mir doch gleich mal wieder der Spruch vom alten Konfuzius ein, der ja angeblich gesagt haben soll: "Je mehr ich weiss, um so mehr weiss ich, dass ich nichts weiss!"
ja, denn wer nichts weiss und weiss, dass er nichts weiss, weiss viel mehr, als der, der nichts weiss und nicht weiss, dass er nichts weiss
gboelter schrieb:
Na ja, ich hab' ja noch ein paar Jahre Zeit das alles zu begreifen ...
noch irgendwelche unklarheiten? frag nur...
-
Apeman schrieb:
ja, denn wer nichts weiss und weiss, dass er nichts weiss, weiss viel mehr, als der, der nichts weiss und nicht weiss, dass er nichts weiss
Danke, das troestet mich ein wenig ...
Apeman schrieb:
noch irgendwelche unklarheiten? frag nur...
Im Moment nicht aber ich werde sicherlich gelegentlich auf Dein Angebot zurueckkommen!
-
Ok, eine Frage haette ich doch noch. Die hat zwar nur noch mittelbar mit dem Thread zu tun hat, doch will ich dafuer nicht extra einen neuen Thread aufmachen:
Hier mal ein Stueck Code aus einem Tutorial:
int main() { int array[] = { 3, 13, 113 }; int n = sizeof(array)/sizeof(array[0]); print(array, n); } int print(int* const array, int const arrayGroesse) { std::cout << std::endl << "Array:" << std::endl; for (int i=0; i<arrayGroesse; i++) std::cout << array[i] << std::endl; }
Mein Frage ist nun, warum wird die Funktion mit
int print(int* const array, int const arrayGroesse) {
aufgerufen, wo doch
int print(int* array, int arrayGroesse) {
auf funktionieren wuerde.
Gruss
Guenther
-
dieses 'const' vor den funktionsparametern sagt dem compiler, dass die funktion die parameter nicht verändert. ich glaube er kann dann gewisse annahmen machen und entsprechend besser optimieren. mir persönlich ist aber noch nie aufgefallen, dass 'const' an der stelle irgendwas bringt. ich denke, du kannst es daher auch weglassen.
-
Zumindest kann man den Wert dann nicht aus versehen in der Funkton ändern.
-
Da ich in letzter Zeit viel in C programmiert habe, mal ein paar Fragen, wofür ich jetzt keinen neuen Thread aufmachen will.
CStoll schrieb:
Es wird ein Parameter vom Typ "const char*" (Zeiger auf ein konstantes char(Array)) übergeben - und Strings werden in C als char-Arrays umgesetzt.
Wo wird den die Zeichenkette "/tmp/virtual.dump" erzeugt? Im Stack der aufgerufenden Funktion nehme ich an?
int meineFunktion(MeinStruct* meinstruct) { // veraendern von meinstruct } void main(...) { MeinStruct meinstruct = { 0 }; meineFunktion(&meinstruct); }
So kann man ja Parameter als Referenz uebergeben. Aber eins verstehe ich nicht ganz, meinstruct liegt doch im Stack von main(), *meinstruct zeigt also doch auf den Stack-Speicher von main(). Wieso kann dann die Funktion meineFunktion() den Stack von main() zugreifen/veraendern?
Liegt es daran, dass der Stack-Bereich von meineFunktion() im Stack von main() liegt?
-
So weit ich weiß gibt es doch nur einen Stack. Rufst du eine Funktion auf werden Rücksprungadresse, Parameter, lokale Variablen usw. auf den Stack "gepusht". Die "darunter" liegenden Daten bleiben dabei erhalten. Deshalb bleiben Adressen konsistent, man kann sie also bis zur Freigabe des jeweiligen Stack-Bereichs benutzen.
Gruß
Don06
-
vielleicht sollte man sich nicht so sehr von dieser 'stack-sichtweise' beeinflussen lassen. wichtig ist ja nur der gültigkeitsbereich der objekte und der endet mit der schliessenden } des blocks, in dem sie angelegt wurden.
-
gboelter schrieb:
int print(int* array, int arrayGroesse) {
Ja, in diesem Fall funktioniert das auch, aber nicht mehr, wenn man ein konstantes Array ausgeben will. Dann müsste man einen const-Pointer in einen normalen Pointer casten.
-
Apeman schrieb:
vielleicht sollte man sich nicht so sehr von dieser 'stack-sichtweise' beeinflussen lassen. wichtig ist ja nur der gültigkeitsbereich der objekte und der endet mit der schliessenden } des blocks, in dem sie angelegt wurden.
endlich mal was Vernueftiges von dir. Das stimmt ja das die Gueltigkeit erst mit dem Block endet. Naja hab lange nicht mehr mich selber um Speicher gekuemmert. Habs auch bemerkt, hab bei dem C Programm mehrmals ein free() vergessen