'int* x' 'int * x' oder 'int *x' ?



  • Tachyon schrieb:

    Grund: Es liest sich schön von hinten nach vorne. Vor allem, wenn noch const im Spiel ist: 🤡

    Ja, wirklich schauderhaft, daß in C das Assignment wechselt. Meist links nach rechts, aber dann bei so "unwesentlichen" Dingen rechts nach links.

    int const *       p, q, r; //p ist pointer auf konstanten int
    int * const       p, q, r; //p ist konstanter pointer auf int
    int const * const p, q, r; //p ist konstanter pointer auf konstanten int
    

    Ich kann ad hoc nicht so einfach sagen, was pointer, was nur int. usw ist, wenn da drei Vars hinter so etwas klemmen, deswegen hat Shadys Beharren auf separate Deklarationen schon was für sich. Man programmiert ja nicht nur in C ... 😉



  • Tachyon schrieb:

    Ich nehme immer

    int * p; //p ist pointer auf int
    

    Grund: Es liest sich schön von hinten nach vorne. Vor allem, wenn noch const im Spiel ist:

    int const *       p; //p ist pointer auf konstanten int
    int * const       p; //p ist konstanter pointer auf int
    int const * const p; //p ist konstanter pointer auf konstanten int
    

    🤡

    sticky!!! - und die prioritätentabelle auch! 😉



  • pointercrash() schrieb:

    ... deswegen hat Shadys Beharren auf separate Deklarationen schon was für sich. Man programmiert ja nicht nur in C ... 😉

    Achso ja, das hätte ich noch dazu schreiben sollen: Selbstverständlich nur eine Variable pro Statement. 😉
    Schreibfaulheit führt selten zu verständlichem Code.



  • Aber es hat nichts mit Schreibfaulheit zu tun, so etwas vermeiden zu wollen:

    /* the x-coordinate of the point */
    double x;
    
    /* the y-coordinate of the point */
    double y;
    
    /* the z-coordinate of the point */
    double z;
    

    Das hat allenfalls Vorteile, wenn die Produktivität der Programmierer anhand der geschriebenen Codezeilen gemessen wird 🙂

    Dass es selten sinnvoll sein dürfte, Integer und Zeiger zusammen einem Statement zu deklarieren wie im Beispiel von pointercrash, ist ja keine Frage.



  • namespace invader schrieb:

    Dass es selten sinnvoll sein dürfte, Integer und Zeiger zusammen einem Statement zu deklarieren wie im Beispiel von pointercrash, ist ja keine Frage.

    Tatsächlich schonmal gesehen, war ein total vergurktes Projekt, das ich "aufräumen" sollte, vor solchen "Tricks" nebst unglaublichen Kommentaren strotzte :p und zudem ein wüster Mix aus C und C++ war. Ich habe nach ein paar Tagen 😕 entnervt aufgegeben 😞
    Ist halt eins der Handwerkszeuge, total unleserlichen Code zu schaffen. 😃



  • namespace invader schrieb:

    Aber es hat nichts mit Schreibfaulheit zu tun, so etwas vermeiden zu wollen:

    //x,y,z coordinates of point whatever
    double x;
    double y;
    double z;
    


  • //x,y,z coordinates of point whatever
    double x,y,z;
    

    Ist doch ok. Ich bin auch kein Freund von Mehr-Variablen-Deklarationen in einer Zeile, aber in solchen Fällen leidet die Übersicht imho nicht.



  • Wenn ich das mit den Pointer-Deklarationen bisher richtig beobachtet habe:

    Eine Typdeklaration besteht aus

    [Typ] [Bezeichner]
    also
    [int] [a]
    oder
    [Typ] [Bezeichner], [Bezeichner], ... [Bezeichner];
    

    Das dämliche an Pointern in C ist jetzt, dass sie so gesehen zum Bezeichner gehören!

    Deswegen:

    [Typ] [[Pointer]Bezeichner] => [int] [[*] p];
    oder
    [int] [[*] p1], [[*] p2];
    oder
    [int constant] [[* constant] p];
    

    hässlich, dämlich, aber C. 🙂

    Wenn das nicht irgendwo an einem Beispiel kollidiert, ist das wohl eine brauchbare Erklärung.
    "int * p" wäre dann wohl korrekt, "int *p" würde die Zugehörigkeit zum Bezeichner verdeutlichen, "int* p" wäre verwirrend.

    Steht das nicht im Standard genau beschrieben? Ich habe leider keinen zur Hand...



  • Nagila Hawa schrieb:

    Das dämliche an Pointern in C ist jetzt, dass sie so gesehen zum Bezeichner gehören!

    typedef int* intp;
    intp p;
    
    void f(int*);
    
    sizeof(int*);
    

    Irgendwie so ganz zum Bezeichner gehört es wohl doch nicht?



  • sie gehören natürlich nicht zu den Bezeichnern, aber in einer Form "[Typ] [Bezeichner]" zur Deklaration gehören sie scheinbar zum Feld Bezeichner. Das ist ja gerade das dämliche.

    Es wird zwischen normalen Typen und Pointertypen unterschieden. Man kann ja von mir aus auch schreiben:

    [Typ] [Pointer] [Bezeichner]
    

    Wenn man sich aber wieder die Deklaration mehrerer Variablen eines Typs in einer Zeile ansieht,

    int *p1, *p2;
    

    was gehört dann in der Hinsicht zusammen?

    Wenn das "*" auch in der Deklaration zum Teil des Typs gehört, müsste man ja

    int * p1, p2;
    

    schreiben können um 2 Pointer zu haben, weil der Typ "int *", also ein Pointer auf int ist. Das funktioniert in dieser Deklaration aber nicht, sondern nur, wenn man vorher einen Pointertyp über Typedef definiert, wie du es ja gemacht hast.



  • Wenn das "*" auch in der Deklaration zum Teil des Typs gehört, müsste man ja ...

    Vieles in C++ ist aus Gruender der Kompatibilitaet dort und aus keinem anderen Grund.



  • knivil schrieb:

    Vieles in C++ ist aus Gruender der Kompatibilitaet dort und aus keinem anderen Grund.

    wie jetzt? hier ist doch das C forum.
    🙂



  • Siehe dritter Post ... Ausserdem steht immer C/C++ vor den Code Tags, wurde auch in anderen Post angesprochen und C ist ne Untermenge ... blablabla



  • Nagila Hawa schrieb:

    hässlich, dämlich, aber C. 🙂

    Blasphemie!

    Und Zeiger gehören nicht zu Bezeichnern, sondern zu Deklaratoren.

    Deklarationen bestehen vereinfacht gesagt aus einem Grundtyp, der einen Typnamen und Dinge wie const oder volatile enthält, und eventuell mehreren Deklaratoren. In jedem Deklarator befindet sich in der Mitte der Bezeichner, der deklariert wird, und um ihn herum Sterne für Zeiger, eckige Klammern für Arrays und runde Klammern für Funktionen. Man muss den Deklarator also von innen nach außen lesen, wenn man wissen will, was man mit dem deklarierten Bezeichner machen muss, um den Grundtyp zu bekommen.

    Ich finde das wunderschön 😃

    int x;          /* ein Integer */
    int x0();       /* eine Funktion, die einen Integer liefert */
    int x1[5];      /* ein Array von Integern */
    int *x2;        /* ein Zeiger auf einen Integer */
    int **x3;       /* ein Zeiger auf einen Zeiger auf einen Integer */
    int x4[5][5];   /* ein Array von Arrays von Integern (a.k.a. 2D-Array) */
    int *(x5());    /* eine Funktion, die einen Integer-Zeiger liefert */
    int (*x6)();    /* ein Zeiger auf eine Funktion, die einen Integer liefert */
    int *(x7[5]);   /* ein Array von Integer-Zeigern */
    int (*x8)[5];   /* ein Zeiger auf ein Integer-Array */
    int *((*x9)[5]);/* ein Zeiger auf ein Array von Integer-Zeigern */
    
    /* ein Array aus Zeigern auf Funktionen, die Zeiger auf Arrays von Zeigern
       auf Funktionen liefern, die einen Integer als Parameter erwarten und
       Zeiger auf Integer liefern */
    int *((*((*((*(xboss[5]))()))[5]))(int));
    

    (redundante Klammern zum besseren Verständnis)



  • Nagila Hawa schrieb:

    sie gehören natürlich nicht zu den Bezeichnern, aber in einer Form "[Typ] [Bezeichner]" zur Deklaration gehören sie scheinbar zum Feld Bezeichner. Das ist ja gerade das dämliche.

    int *f();

    gehört der * da immer noch zu f?
    Warum muss ich dann klammern wenn ich
    int (*f)();
    will?



  • Shade Of Mine schrieb:

    int *f();

    gehört der * da immer noch zu f?

    Sowohl der Zeiger-Stern links als auch die Funktions-Klammern rechts gehören zum Deklarator. Die Funktions-Klammern haben aber eine höhere Präzedenz, deswegen muss man zusätzlich klammern, wenn man es andersrum haben will.

    Das ist nur konsistent dazu, dass Postfix-Operatoren eine höhere Präzedenz haben als unäre. Und dass der Zeiger-Stern eine höhere Präzedenz hat als das Komma zwischen Deklaratoren (was dazu führt, dass bei "int *x, y;" y kein Zeiger ist) ist auch konsistent zur niedrigen Präzedenz des normalen Komma-Operators.



  • namespace invader schrieb:

    Sowohl der Zeiger-Stern links als auch die Funktions-Klammern rechts gehören zum Deklarator.

    Und bei
    int i;

    gehoert das int auch zum deklarator.

    Irgendwie witzlos, oder? 😉



  • Shade Of Mine schrieb:

    Und bei
    int i;

    gehoert das int auch zum deklarator.

    Nein, eben nicht. Deshalb steht es bei einer Deklaration nur einmal da, auch wenn es mehrere Deklaratoren gibt.

    (Was ist eigentlich im Moment das Thema der Diskussion? 😕)



  • namespace invader schrieb:

    Was ist eigentlich im Moment das Thema der Diskussion? 😕)

    Wohin das Sternchen gehört, möglichst mit logischer Begründung, nur so zur Erinnerung .... 🙄



  • Ich glaube fast, dass sie nach endlosen Diskussionen mit gewichtigen Argumenten auf beiden Seiten gesagt haben: okay, lassen wir beides zu 🙂

    Und ja Shade, genau das Ding mit dem Funktionszeiger ist die 'Lücke', da ist syntaktisch sonst nicht anders ranzukommen.


Anmelden zum Antworten