Unterschiedliche Zeigernotationen



  • Hallo Forum,
    mir ist beim Einarbeiten in C++ aufgefallen, dass oftmals unterschiedliche Zeigernotationen verwendet werden (ebenso bei Referenzen). Kann mir jemand sagen, was der Unterschied folgender Notationen ist:

    int* datum1;
    int *datum2;
    *int datum3;
    int datum4*;
    

    Danke
    Martin



  • skifidelity schrieb:

    Kann mir jemand sagen, was der Unterschied folgender Notationen ist:

    int* datum1;
    int *datum2;
    

    Sind identisch

    skifidelity schrieb:

    *int datum3;
    int datum4*;
    

    Wäre mir neu, das dies gültig wäre.



  • Schließe mich asc an. Bei deinen ersten beiden Beispielen ist es egal wie viele Leerzeichen dazwischen sind. Somit sind sie exakt gleich.



  • Davon abgesehen gibt es noch viel gemeinere Konstrukte:

    int * a;             // Identisch mit deinen ersten beiden - verwende ich inzwischen.
    const int * a;       // \ Zeiger auf Konstenten Wert, ich verwende die zweite
    int const * a;       // / Schreibweise wegen den weiter unten stehenden Fällen.
    int * const a;       // Konstanter Zeiger, auf nicht Konstanten Wert
    const int * const a; // \ Konstanter Zeiger auf Konstanten Wert.
    int const * const a; // /
    

    Um einheitlich zu sein schreibe ich das const immer hinter dem Teil, der konstant ist (Lies: int-Konstante Zeiger-Konstante).

    Warum ich den Zeiger nicht mehr an die Variable schreibe, oder an den Typ hänge, liegt vor allem daran, das ich eine einheitliche Schreibweise vorziehe (Bei const müsste ich sonst wieder davon abweichen).



  • Das ist eine Glaubensfrage ob du

    int* a;
    

    oder

    int *a;
    

    benutzt

    Ich tendiere zu zweiter Variante weil bei ich gewohnt bin soetwas:

    double a,b,c,d;
    

    als "4 Variablen vom Typ double" zu lesen.

    Wenn du aber sowas schreibst

    double* a,b,c,d;
    

    ist a ein Pointer auf einen double während b,c und d einfach nur double Variablen sind (keine Pointer!). Folglich modifiziert das '*' das a und nicht das 'double'.

    Um 4 pointer auf einmal zu deklarieren musst du sowas machen:

    double *a, *b, *c, *d;
    

    und da fänd ich die Schreibweise

    double* a, *b, *c, *d;
    

    unlogisch.



  • Da man aber sowas in C++ nicht macht, fällt die Begründung weg.



  • Und wieso 'macht man sowas nicht'? Gibts dafür nen triftigen Grund? Oder gar eine göttliche Richtlinie? Oder hast du noch nie

    int i,j,k;
    

    in einer Zeile deklariert?



  • antialias schrieb:

    Und wieso 'macht man sowas nicht'? Gibts dafür nen triftigen Grund? Oder gar eine göttliche Richtlinie? Oder hast du noch nie

    int i,j,k;
    

    in einer Zeile deklariert?

    Weil es in C++ nicht notwendig ist, Variablen am Anfang der Funktion zu deklarieren.
    Objekte werden deklariert und sofort initialisiert, so eine reihenweise Default-Initialisierung ist einfach nicht nötig.



  • antialias schrieb:

    Und wieso 'macht man sowas nicht'? Gibts dafür nen triftigen Grund? Oder gar eine göttliche Richtlinie? Oder hast du noch nie

    int i,j,k;
    

    in einer Zeile deklariert?

    Ja, die Richlinien heißen
    - Mach Variablen so lokal wie möglich.
    und als ein Aspekt davon
    - Versuche die Definition zu verzögern, bis Du eine sinnvolle Initialisierung angeben kannst.

    Klar habe ich damals

    int i,j,k;
    

    geschrieben, aber das war in C. Und natürlich eine Zeit lang weiter als C++-Neuling.


  • Mod

    1. Deklariert man Variablen dort wo man sie braucht und mehrere Variablen vom gleichen Typ braucht man selten an der gleichen Stelle.
    2. Initialisiert man dann ja auch gleich die Variablen
    3. Und spätestens bei 2. wird es extrem unübersichtlich mehrere Variablen in einer Zeile zu deklarieren
    4. Und da man es einheitlich machen will, macht man es halt nirgends, selbst wenn tatsächlich mal der Fall vorkommen würde, wo man zwei oder mehr uninitialiserte Variablen vom gleichen Typ an der gleichen Stelle benötigen würde.

    Und 5.: Nein, aus den oben genannten Gründen mache ich nie (oder besser gesagt nicht mehr) int a,b,c;

    edit: Zu langsam.



  • antialias schrieb:

    Und wieso 'macht man sowas nicht'?

    Ich mache so etwas durchaus noch, aber ausschließlich in einer for-Schleife:

    for(auto pos=v.begin(), end=v.end(); pos!=end; ++pos)
    

    Und ansonsten kann ich mich den Vorpostern nur anschließen.



  • asc schrieb:

    Ich mache so etwas durchaus noch, aber ausschließlich in einer for-Schleife:

    for(auto pos=v.begin(), end=v.end(); pos!=end; ++pos)
    

    Der Unterschied ist der, dass du auch gleich richtig initialisierst! Neben dem dass es in diesem Fall gar nicht anders geht, pos und end so lokal wie nötig (in der Schleife) zu halten.



  • Tja, dacht ich mir, dass das einen Glaubenskrieg auslöst 😃

    Das Beispiel war auch nur da um zu verdeutlichen:
    Ein Pointer ist ein Pointer ist ein Pointer.

    int *ptr;
    double *ptr;
    myObject *ptr;
    

    Was ausgegeben wird, wenn man den Inhalt von ptr irgendwohin schreibt, ist immer das gleiche: eine Adresse.
    int, double oder myObject werden durch das '*' nicht modifiziert, also gehört (für mich) der Stern da auch nicht hin.

    Bestes Beispiel, dass der Stern nix mit dem Variablentyp zu tun hat ist, dass du sowas machen kannst:

    void *ptr;
    

    Derzeit muss ich mich mit Code rumschlagen wo die

    int * a;
    

    Schreibweise präferiert wird. Ich finde, dass das beim Überfliegen des Codes jedoch zu sehr wie eine Multiplikation aussieht (sprich: man denkt da tut sich was interessantes - dann schaut man doch genauer hin und entdeckt, dass es bloss eine Deklaration ist....nerv).

    Das 'so lokal wie möglich' hab ich inzwischen auch wieder aufgegeben. In wissenschaftlichem Code zerreisst es den Denkfluss. Man hat genug damit zu tun nachzuvollziehen was passiert, ohne durch zwischenzeitliche Variablendeklarationen ausm Konzep gebracht zu werden.

    Und ja: das ist meine, ganz subjektive, Meinung.



  • antialias schrieb:

    Tja, dacht ich mir, dass das einen Glaubenskrieg auslöst 😃
    Das Beispiel war auch nur da um zu verdeutlichen:
    Ein Pointer ist ein Pointer ist ein Pointer.

    int *ptr;
    double *ptr;
    myObject *ptr;
    

    Was ausgegeben wird, wenn man den Inhalt von ptr irgendwohin schreibt, ist immer das gleiche: eine Adresse.
    int, double oder myObject werden durch das '*' nicht modifiziert, also gehört (für mich) der Stern da auch nicht hin.

    Und andere meinen, daß bei

    int* pa;
    

    pa den Typ "Zeiger auf int" hat.
    Und

    typedef int* pint;
    pint pa;
    

  • Mod

    antialias schrieb:

    Das 'so lokal wie möglich' hab ich inzwischen auch wieder aufgegeben. In wissenschaftlichem Code zerreisst es den Denkfluss. Man hat genug damit zu tun nachzuvollziehen was passiert, ohne durch zwischenzeitliche Variablendeklarationen ausm Konzep gebracht zu werden.

    Komisch, ich arbeite auch mit wissenschaftlichem Code und bin genau der gegenteiligen Ansicht.

    Und ja: das ist meine, ganz subjektive, Meinung.

    Na dann. Jeder nach seinem Geschmack. Aber ich erlaube mir, froh darüber zu sein, dass wir nicht gegenseitig unseren Code austauschen 🙂 .



  • Aber ich erlaube mir, froh darüber zu sein, dass wir nicht gegenseitig unseren Code austauschen 🙂 .

    Da sind wir ja wenigstens hier einer Meinung 😃



  • typedef int* pint;
    pint pa;
    

    Die typedef liste am Anfang deiner Projekte möcht ich nicht sehen 😃

    typedef int* pint;
    typedef float* pfloat;
    typedef myClass1* pmyClass1;
    typedef myClass2* pmyClass2;
    typedef myClass3* pmyClass3;
    typedef myClass4* pmyClass4;
    .
    .
    .
    

    Gerade ausprobiert: vs2008 macht dabei zumindest nichtmal ein highlight bei 'pint'. Das ist noch viel unleserlicher als

    int* p
    


  • antialias schrieb:

    int, double oder myObject werden durch das '*' nicht modifiziert, also gehört (für mich) der Stern da auch nicht hin.

    Der "*" gehört ganz eindeutig zum Typen und nicht zur Variablen, nur kann man das in C++ nicht wirklich formulieren.

    #include <typeinfo>
    #include <iostream>
    
    int main () {
        std::type_info const& ti  = typeid(int);
        std::type_info const& tip = typeid(int*);
        std::type_info const& tlp = typeid(long*);
    
        std::cout << std::boolalpha;
        std::cout << (tip == tlp) << std::endl;
        std::cout << (ti == tip) << std::endl;
    }
    

    typedefs belegen dies ebenfalls.



  • [quote="~john"]Der "*" gehört ganz eindeutig zum Typen und nicht zur Variablen, nur kann man das in C++ nicht wirklich formulieren./quote]
    Nein.
    Sowohl

    int* pi;
    

    "pi ist vom Typ Zeiger auf int."
    als auch

    int *pi;
    

    "Das, wo pi hinzeigt, ist vom Typ int."
    sind sinnvoll, fürchte ich.



  • ~john schrieb:

    #include <typeinfo>
    #include <iostream>
    
    int main () {
        std::type_info const& ti  = typeid(int);
        std::type_info const& tip = typeid(int*);
        std::type_info const& tlp = typeid(long*);
    
        std::cout << std::boolalpha;
        std::cout << (tip == tlp) << std::endl;
        std::cout << (ti == tip) << std::endl;
    }
    

    Was soll uns das zeigen? 😕


Anmelden zum Antworten