Verständniss frage zu Zeigern
-
Hallo,
zwischen operatoren und operanden dürfen 0 bis n Whitespaces stehen. Das gilt auch für die Deklaration von Zeigern. Es ist also völlig gleichgültig ob Du
TYPE*zeiger; TYPE * zeiger; TYPE* zeiger; oder TYPE *zeiger;schreibst.
Nur: Die Lesbarkeit des Codes für menschliche Leser sollte gewährleistet sein. Auch sollte innerhalb eines Quelltextes die verschiedenen Schreibweisen nicht gemischt werden. Dem Compiler ist das aber wurscht.
mfg Martin
-
Oh wow danke leute für die Antworten

also ist es völlig egal ob ich es links oder rechts schreibe. Ich habe mir es in der kurzen Zeit nämlich so angewohnt es rechts beim Pointer und nicht beim Typ zu schreiben.danke euch

-
Dravere schrieb:
Oder man definiert auf einer Zeile nur eine Variable. In C musste man früher alle Variablen im Kopf der Funktion definieren, daher mag das vielleicht etwas kompakter gewirkt haben, wenn man mehrere Variablen auf einer Zeile definiert hat. In neuerem C und auch in C++ definiert man die Variablen sowieso erst bei der ersten Verwendung, daher sind es meistens sehr wenig auf einmal, und man kann pro Zeile eine Variable hinschreiben, ohne dass man nun 20 Zeilen Variablendefinitionen hat

Da kommt noch hinzu, dass lokale Zeiger kaum bis gar nicht vorkommen. In C++ hat man Referenzen, Iteratoren und Smartpointer, rohe Zeiger aber fast nie.
Lediglich bei Klassen findet man die noch gelegentlich und bei Klassendeklaration ist eine Variable pro Zeile ohnehin allgemein üblich.Also kann man den Stern getrost da hinsetzen, wo er hingehört: zum Typen. :p
-
Athar schrieb:
Da kommt noch hinzu, dass lokale Zeiger kaum bis gar nicht vorkommen. In C++ hat man Referenzen, Iteratoren und Smartpointer, rohe Zeiger aber fast nie.
Lediglich bei Klassen findet man die noch gelegentlich und bei Klassendeklaration ist eine Variable pro Zeile ohnehin allgemein üblich.Also kann man den Stern getrost da hinsetzen, wo er hingehört: zum Typen. :p
Referenzen benutze ich nur, wenn es unbedingt sein muß oder der Lesbarkeit dient. Normalerweise also gar nicht.
void func1( TYPE *pointer ); void func2( TYPE &pointer ); void func3( void ) { TYPE value; func1( &value ); // hier sehe ich sofort, daß der Parameter by reference übergeben wird func2( value ); // hier muß ich mir die Funktionsdeklaration anschauen }Der Stern gehört nicht zum Typen sondern zur Variable, da er sich nur dort auswirkt;
TYPE *pointer, value; // Hier wird ein Zeiger und ein Objekt deklariert.mfg Martin
-
@mgaeckler: Da bist du aber ziemlich alleine mit deinem Geschmack. Überhaupt ist auch call-by-(nicht konstanter)-reference eher ungewöhnlich in C++, wenn man es nicht mit dehr großen Objekten zu tun hat.
-
mgaeckler schrieb:
void func1( TYPE *pointer ); void func2( TYPE &pointer ); void func3( void ) { TYPE value; func1( &value ); // hier sehe ich sofort, daß der Parameter by reference übergeben wird func2( value ); // hier muß ich mir die Funktionsdeklaration anschauen }Hmm eine frage zu diesem Code. Habe ich das richtig verstanden das beide Funktionen den gleichen Parameter haben ? also ist es egal ob bei der Funktion
Funktion (TYPE *Pointer)definiere und dann beim Aufruf
Funktion( &value ).
oder es so mache
Funktion (TYPE &Pointer)und beim aufruf dann so
Funktion( value )??
lg chris
-
mgaeckler schrieb:
[...]
func1( &value ); // hier sehe ich sofort, daß der Parameter by reference[...]
Und was hilft Dir dieses Wissen? Du weisst immer noch nicht, ob der Wert geändert wird, oder nicht oder ob es ein Zeiger auf const ist, oder nicht. Ergo hasst Du keine Ahnung, was mit dem Wert passiert...
-
Tachyon schrieb:
mgaeckler schrieb:
[...]
func1( &value ); // hier sehe ich sofort, daß der Parameter by reference[...]
Und was hilft Dir dieses Wissen? Du weisst immer noch nicht, ob der Wert geändert wird, oder nicht oder ob es ein Zeiger auf const ist, oder nicht. Ergo hasst Du keine Ahnung, was mit dem Wert passiert...
In C++ hilft es mir tatsächlich wenig, weil es ja eine Referenz sein könnte. In C sehe ich durch die Parameterübergabe by value sofort beim Aufrufer, daß der Wert nicht verändert werden kann. In C++ ist beim Aufruf kein Unterschied zwischen der Parameterübergabe by value und by referenz.
mfg Martin
-
CodeBase schrieb:
Hmm eine frage zu diesem Code. Habe ich das richtig verstanden das beide Funktionen den gleichen Parameter haben ? also ist es egal ob bei der Funktion
Funktion (TYPE *Pointer)definiere und dann beim Aufruf
Funktion( &value ).
oder es so mache
Funktion (TYPE &Pointer)und beim aufruf dann so
Funktion( value )??
lg chris
Semantisch ist beides das gleiche. func1 und func2 bekommen beide die Adresse von value.
mfg Martin
-
mgaeckler schrieb:
Semantisch ist beides das gleiche. func1 und func2 bekommen beide die Adresse von value.
mfg Martin
Das stimmt nicht. Im ersten Fall hat man eine Übergabe per Wert (der Wert des Zeigers).
Im zweiten Fall hat man eine Übergabe per Referenz, also das Objekt selbst unter dem Namen des formalen Parameters. Hinter der Referenz kann zwar Zeigermechanik am werkeln sein, muss aber nicht.
-
Der Stern gehört logisch zum Typen, da ändert es auch nichts, dass die C-Designer raffiniert sein wollten.
Warum man diese Eigenheit ignorieren kann, haben Dravere und ich schon erläutert.Wenn du eine Funktion aufrufst, wär's übrigens nicht ganz verkehrt, wenn du weißt, was für Parameter sie erwartet und wozu sie verwendet werden. Woraus sich alles weitere ergibt.
Wenn du gerade fremden Code liest, gibt es notfalls Calltips zur schnellen Aufklärung, wenn etwas mal nicht eindeutig sein sollte.
-
Tachyon schrieb:
Das stimmt nicht. Im ersten Fall hat man eine Übergabe per Wert (der Wert des Zeigers).
Im zweiten Fall hat man eine Übergabe per Referenz, also das Objekt selbst unter dem Namen des formalen Parameters. Hinter der Referenz kann zwar Zeigermechanik am werkeln sein, muss aber nicht.Das sind Implementierungsdetails, die den Compilerbauer interessieren. Für den C++-Programmierer ist es Jacke wie Hose. Deswegen schrieb ich ja auch "semantisch".
void func1( TYPE *pointer ) { *pointer = value: } void main( void ) { TYPE variable; func1( &variable ); }und
void func1( TYPE &reference ) { reference = value: } void main( void ) { TYPE variable; func1( variable ); }machen exakt das gleiche.
mfg Martin
-
Athar schrieb:
Der Stern gehört logisch zum Typen, da ändert es auch nichts, dass die C-Designer raffiniert sein wollten.
Warum man diese Eigenheit ignorieren kann, haben Dravere und ich schon erläutert.Wer war eher da, Huhn oder Ei?
Vom Bauchgefühl würd ich dir ja recht geben. Aber mein Kopf stellt sich die Frage, warum der * logisch zum Typen gehört, wenn die Assoziativität ihn an die Variable bindet? Vielleicht hatte the god father of C da eine andere Logik...
-
typedef int * pint; pint p;lese ich als
int * p;Damit gehört für mich der * zum Typ.
Klappt natürlich nur, wenn man für jede Variable eine eigene Zeile opfert, aber das mache ich gerne. Im Weiteren schließe ich mich Dravere an.
-
SeppJ schrieb:
@mgaeckler: Da bist du aber ziemlich alleine mit deinem Geschmack. Überhaupt ist auch call-by-(nicht konstanter)-reference eher ungewöhnlich in C++, wenn man es nicht mit dehr großen Objekten zu tun hat.
Das mag sein. Jahrelange Arbeit mit C hat natürlich meinen Stil geprägt. Mag sein, daß er anders wäre, wenn ich gleich mit C++ angefangen hätte. Das gab's damals aber noch nicht.
Ich habe mir es so angewöhnt:
Funktionen, die größere Objekte erhalten ohne sie verändern zu wollen, definiere ich mit const referenzen. Funktionen, die die Werte verändern wollen, bekommen einen Zeiger.
mfg Martin
-
mgaeckler schrieb:
Ich habe mir es so angewöhnt:
Funktionen, die größere Objekte erhalten ohne sie verändern zu wollen, definiere ich mit const referenzen. Funktionen, die die Werte verändern wollen, bekommen einen Zeiger.So mache ich es auch und es gefällt mir sehr gut.
-
Athar schrieb:
Der Stern gehört logisch zum Typen, da ändert es auch nichts, dass die C-Designer raffiniert sein wollten.
Das stimmt, da er sich aber nur auf die nachfolgende Variable, der Typ auf alle Variablen der Deklaration bezieht, ist es trotzdem besser, den * bei der Variable zu schreiben.
Athar schrieb:
Wenn du eine Funktion aufrufst, wär's übrigens nicht ganz verkehrt, wenn du weißt, was für Parameter sie erwartet und wozu sie verwendet werden. Woraus sich alles weitere ergibt.
Korrekt, dem habe ich nichts hinzuzufügen.
Athar schrieb:
Wenn du gerade fremden Code liest, gibt es notfalls Calltips zur schnellen Aufklärung, wenn etwas mal nicht eindeutig sein sollte.
Calltips hat man aber nicht immer zur Verfügung, deshalb habe ich es lieber, wenn ich beim Aufrufer sehe, was Sache ist.
Ich habe mir das ganze schon vor Jahren angewöhnt und benutze auch heute noch Editoren, die das eben nicht können (vi, Borland C++ um nur zwei Beispiele zu nennen)
mfg Martin
-
volkard schrieb:
typedef int * pint; pint p;lese ich als
int * p;Damit gehört für mich der * zum Typ.
Klappt natürlich nur, wenn man für jede Variable eine eigene Zeile opfert, aber das mache ich gerne. Im Weiteren schließe ich mich Dravere an.Wobei das wiederum eher die typedef-Syntax betrifft als die "Logik" des *.
Wie gesagt, vom Bauch her teile ich die Logik, dass der Pointer ein Typ ist und seine "Bezeichnung" zur Typbezeichnung gehört. Aber die Syntax sagt nunmal was anderes...
Wobei ich solche Diskussionen immer spannend finde. Bei Text- oder Bildinterpretationen, wie man sie in der Schule macht, diskutieren Leute ewig darüber, was der der Schöpfer mit der Aliteration oder Farbmischung ausdrückung möchte. Vielleicht ist dem Autor kein Wort mit einem anderen Buchstaben eingefallen und begeisternde Farbvariationen haben ja bekanntlich auch "künstlerisch hochbegabte" Affen geschafft.
Sich darüber zu streiten, was "üblich" ist, was "guter Stil" ist, was "logisch" ist oder auch "dumm", wären alle einer Meinung, gäbe es keinen Fortschritt mehr.Um zum Thema zurückzukommen: vielleicht ändert jemand die Syntax so, dass
type* pMyVar1, pMyVr2;zwei Pointer deklariert. Solange das nicht so ist, gehört der Stern logisch "nach rechts". Wo man ihn hinschreibt, bleibt nach wie vor scheiß egal.
-
mgaeckler schrieb:
[...]Das sind Implementierungsdetails, die den Compilerbauer interessieren. Für den C++-Programmierer ist es Jacke wie Hose. Deswegen schrieb ich ja auch "semantisch".[...]
Eben nicht. Übergabe per Wert bzw. als Referenz interessiert mich als Entwickler, weil es einige große Unterschiede gibt.
Referenzen kann man z.B. nicht auf Referenzen zeigen lassen. Auf Zeiger hingegen schon. Zeiger dürfen auf NULL bzw. auf ungültige Werte Zeigen. Referenzen hingegen nicht. Einen Zeiger kann ich beliebig auf irgendetwas zeigen lassen, weil es eine normale Variable eines Zeigertyps ist. Auf Referenzen trifft das nicht zu.
Deine Aussagemgaeckler schrieb:
func1 und func2 bekommen beide die Adresse von value.
ist falsch.
-
Natürlich gehört der * zum Typ. Aber [] bei Arrays gehört auch zum Typ. Überhaupt gehört in einer Deklaration alles außer dem deklarierten Namen zum Typ:
void (*f)(int(&)[10]); //<-----> <-----------> // Typ ^ auch Typ // | // Bezeichner