Warum steht das Sternchen vor dem Variablennamen und nicht nach dem Typ?

Lesezeit: 9 Minuten

Benutzeravatar von WBlasko
WBlasko

Warum benennen die meisten C-Programmierer Variablen so:

int *myVariable;

statt so:

int* myVariable;

Beides ist gültig. Es scheint mir, dass das Sternchen ein Teil des Typs ist, nicht ein Teil des Variablennamens. Kann jemand diese Logik erklären?

  • Der zweite Stil scheint im Allgemeinen intuitiver zu sein, aber ersterer ist der richtige Weg, um typbezogene Fehler im Code zu vermeiden. Wenn Sie wirklich an letzterem Stil hängen, können Sie immer mitmachen typedefsaber das wird IMHO unnötige Komplexität hinzufügen.

    – Wolke

    8. August 2016 um 15:50 Uhr

  • Ich bin kürzlich hierher gestolpert und habe meinen Teil dazu beigetragen … Stimme @Cloud da völlig zu typedefDas Setzen von Zeigern ist eine gute Idee – dies verbirgt nur Informationen ohne weiteren Nutzen, abgesehen davon, dass Fehler bei der Deklaration von Variablen vermieden werden – und für letztere besteht der bessere Ansatz darin, nicht mehr als eine einzelne Variable in einer Codezeile zu definieren (wobei anzuerkennen ist, dass dies eine etwas mehr Tipparbeit und ein paar Codezeilen mehr, aber das ist immer noch besser als die typedef…).

    – Aconcagua

    4. Februar um 12:58 Uhr

Benutzeravatar von luiscubal
luiskubal

Sie sind GENAU gleichwertig. Allerdings hinein

int *myVariable, myVariable2;

Es scheint offensichtlich, dass myVariable einen Typ hat int*während myVariable2 den Typ hat int. Im

int* myVariable, myVariable2;

Es mag offensichtlich erscheinen, dass beide vom Typ sind int*aber das ist so nicht richtig myVariable2 Typ hat int.

Daher ist der erste Programmierstil intuitiver.

  • vielleicht, aber ich würde Typen nicht in einer Deklaration mischen und abgleichen.

    – Bobby Shaftoe

    30. Dezember 2008 um 3:13 Uhr

  • @BobbyShaftoe Einverstanden. Auch nachdem ich hier jedes Argument gelesen habe, bleibe ich dabei int* someVar für persönliche Projekte. Es macht mehr Sinn.

    – Alyssa Haroldsen

    27. Februar 2014 um 23:34 Uhr

  • @Kupiakos Es ist nur sinnvoller, bis Sie die Deklarationssyntax von C basierend auf “Deklarationen folgen der Verwendung” lernen. Deklarationen verwenden genau dieselbe Syntax wie die Verwendung von Variablen desselben Typs. Wenn Sie ein Array von Ints deklarieren, sieht es nicht so aus: int[10] x. Das ist einfach nicht die Syntax von C. Die Grammatik analysiert explizit wie folgt: int (*x)und nicht als (int *) xalso ist das Platzieren des Sternchens auf der linken Seite einfach irreführend und basiert auf einem Missverständnis der C-Deklarationssyntax.

    – Spitzenreiter

    31. August 2014 um 20:38 Uhr

  • Korrektur: Daher sollten Sie niemals mehr als eine Variable in einer einzelnen Zeile deklarieren. Im Allgemeinen sollten Sie einen bestimmten Codierungsstil nicht auf der Grundlage eines anderen, nicht verwandten, schlechten und gefährlichen Codierungsstils motivieren.

    – Ludin

    29. Januar 2016 um 10:50 Uhr

  • Aus diesem Grund halte ich mich an eine Variable pro Zeigerdeklaration. Es gibt absolut keine Verwirrung, wenn Sie dies tun int* myVariable; int myVariable2; stattdessen.

    – Patrick Roberts

    11. April 2018 um 5:24 Uhr


Wenn man es anders betrachtet, *myVariable ist vom Typ intwas irgendwie Sinn macht.

  • Dies ist meine Lieblingserklärung und funktioniert gut, weil sie die Eigenarten der Deklaration von C im Allgemeinen erklärt – sogar die ekelhafte und knorrige Funktionszeiger-Syntax.

    – Benjamin Pollack

    29. Dezember 2008 um 19:29 Uhr

  • Es ist irgendwie nett, da Sie sich vorstellen können, dass es keine tatsächlichen Zeigertypen gibt. Es gibt nur Variablen, die Ihnen, wenn sie entsprechend referenziert oder dereferenziert werden, einen der primitiven Typen geben.

    – Biozink

    29. Dezember 2008 um 19:34 Uhr

  • Tatsächlich kann ‘*myVariable’ vom Typ NULL sein. Zu allem Überfluss könnte es auch nur ein zufälliger Speicherort sein.

    – qonf

    26. Januar 2012 um 10:52 Uhr

  • qonf: NULL ist kein Typ. myVariable kann NULL sein, in diesem Fall *myVariable verursacht einen Segmentierungsfehler, aber es gibt keinen Typ NULL.

    – Daniel Röthlisberger

    9. Januar 2013 um 19:02 Uhr

  • Dieser Punkt kann in einem solchen Zusammenhang irreführend sein: int x = 5; int *pointer = &x;weil es vorschlägt, dass wir den int setzen *pointer zu einem gewissen Wert, nicht die pointer selbst.

    – Rafalcieslak

    23. Februar 2013 um 20:04 Uhr


Etwas, das hier bisher noch niemand erwähnt hat, ist, dass dieses Sternchen eigentlich das “Dereferenzierungsoperator„in c.

*a = 10;

Die obige Zeile bedeutet nicht, dass ich zuweisen möchte 10 zu abedeutet dies, dass ich zuweisen möchte 10 an welchen Speicherort auch immer a verweist auf. Und ich habe noch nie jemanden schreiben sehen

* a = 10;

hast du? Also die Dereferenzierungsoperator wird fast immer ohne Leerzeichen geschrieben. Dies dient wahrscheinlich zur Unterscheidung von einer Multiplikation, die über mehrere Zeilen hinweg unterbrochen ist:

x = a * b * c * d
  * e * f * g;

Hier *e wäre irreführend, oder?

Okay, was bedeutet nun eigentlich die folgende Zeile:

int *a;

Die meisten Leute würden sagen:

Das bedeutet es a ist ein Zeiger auf ein int Wert.

Das ist technisch korrekt, die meisten Leute sehen/lesen es gerne so und so würden moderne C-Standards es definieren (beachten Sie, dass die Sprache C selbst allen ANSI- und ISO-Standards vorausgeht). Aber es ist nicht die einzige Möglichkeit, es zu betrachten. Sie können diese Zeile auch wie folgt lesen:

Der dereferenzierte Wert von a ist vom Typ int.

Tatsächlich kann das Sternchen in dieser Deklaration also auch als Dereferenzierungsoperator angesehen werden, was auch seine Platzierung erklärt. Und das a ist ein Zeiger überhaupt nicht wirklich deklariert, ist dies implizit durch die Tatsache, dass das einzige, was Sie tatsächlich dereferenzieren können, ein Zeiger ist.

Der C-Standard definiert nur zwei Bedeutungen für die * Operator:

  • indirekter Operator
  • Multiplikationsoperator

Und Indirektion ist nur eine einzige Bedeutung, es gibt keine zusätzliche Bedeutung für das Deklarieren eines Zeigers, es gibt nur Indirektion, was die Dereferenzierungsoperation tut, sie führt einen indirekten Zugriff durch, also auch innerhalb einer Anweisung wie int *a; dies ist eine indirekte Zugang (* bedeutet indirekter Zugriff) und somit ist die zweite obige Aussage viel näher am Standard als die erste.

  • Danke, dass Sie mich davor bewahrt haben, hier noch eine weitere Antwort zu schreiben. Übrigens lese ich normalerweise die int a, *b, (*c)(); als so etwas wie “deklarieren Sie die folgenden Objekte als int: das Objekt adas Objekt, auf das von gezeigt wird bund das Objekt, das von der Funktion zurückgegeben wird, auf die gezeigt wird c“.

    – Antti Haapala – Слава Україні

    1. Mai 2016 um 7:18 Uhr

  • Das * in int *a; ist kein Operator und dereferenziert nicht a (was noch nicht einmal definiert ist)

    – MM

    8. November 2016 um 5:43 Uhr

  • @MM Bitte nennen Sie die Seiten- und Zeilennummer eines beliebigen ISO-C-Standards, in dem dieser Standard besagt, dass Sternchen etwas anderes als Multiplikation oder Indirektion sein kann. Es zeigt nur “Zeigerdeklaration” als Beispiel, es definiert nirgendwo eine dritte Bedeutung für Sternchen (und es definiert keine Bedeutung, das wäre kein Operator). Oh, ich habe nirgendwo behauptet, dass irgendetwas “definiert” ist, das hast du dir ausgedacht. Oder wie Jonathan Leffler es ausgedrückt hat, im C-Standard ist * immer “Grammatik”, es ist nicht Teil der aufgelisteten Deklarationsspezifizierer (also ist es nicht Teil einer Deklaration, also muss es ein Operator sein)

    – Mecki

    11. Oktober 2017 um 9:25 Uhr


  • @Mecki siehe C11 6.7.6.1/1, die Bedeutung von * in Deklaratoren angegeben ist. Es ist ein Teil der Syntax zum Deklarieren eines Zeigers (z. B. int * a; erklärt a mit Typ “Zeiger auf int“)

    – MM

    12. Oktober 2017 um 0:16 Uhr


  • Es gibt keinen „totalen Ausdruck“. int *a; ist eine Deklaration, kein Ausdruck. a wird nicht dereferenziert von int *a;. a existiert zu dem Zeitpunkt noch gar nicht * wird verarbeitet. Denkst du int *a = NULL; ist ein Fehler, weil er einen Nullzeiger dereferenziert?

    – MM

    12. Oktober 2017 um 22:04 Uhr

Benutzeravatar von ojrac
ojrac

Weil das * in dieser Zeile enger an die Variable als an den Typ bindet:

int* varA, varB; // This is misleading

Wie @Lundin unten betont, fügt const noch mehr Feinheiten hinzu, über die man nachdenken muss. Sie können dies vollständig umgehen, indem Sie eine Variable pro Zeile deklarieren, die niemals mehrdeutig ist:

int* varA;
int varB;

Das Gleichgewicht zwischen klarem Code und prägnantem Code ist schwer zu finden – ein Dutzend redundanter Zeilen int a; ist auch nicht gut. Trotzdem verwende ich standardmäßig eine Deklaration pro Zeile und mache mir Gedanken über das spätere Kombinieren von Code.

Ich werde hier auf die Beine gehen und das sagen Auf diese Frage gibt es eine klare Antwortsowohl für Variablendeklarationen als auch für Parameter- und Rückgabetypen, was bedeutet, dass das Sternchen neben dem Namen stehen sollte: int *myVariable;. Um zu verstehen, warum, schauen Sie sich an, wie Sie andere Symboltypen in C deklarieren:

int my_function(int arg); für eine Funktion;

float my_array[3] für ein Array.

Das allgemeine Muster, bezeichnet als Deklaration folgt Gebrauchbesteht darin, dass der Typ eines Symbols in den Teil vor dem Namen und die Teile aufgeteilt wird um der Name, und diese Teile um den Namen imitieren die Syntax, die Sie verwenden würden, um einen Wert des Typs auf der linken Seite zu erhalten:

int a_return_value = my_function(729);

float an_element = my_array[2];

und: int copy_of_value = *myVariable;.

C++ wirft bei Referenzen einen Strich durch die Rechnung, weil die Syntax an der Stelle, an der Sie Referenzen verwenden, identisch mit der von Werttypen ist, sodass Sie argumentieren könnten, dass C++ einen anderen Ansatz als C verfolgt. Auf der anderen Seite behält C++ dasselbe bei Verhalten von C im Fall von Zeigern, daher stehen Referenzen in dieser Hinsicht wirklich auf der Kippe.

  • Außer const * const *const x folgt nicht der Verwendung

    – Lewis Kelsey

    14. August um 11:13 Uhr


Ein großer Guru sagte einmal: „Lies es so wie der Compiler, du musst.“

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

Zugegeben, das war zum Thema Konstantenplatzierung, aber hier gilt die gleiche Regel.

Der Compiler liest es wie folgt:

int (*a);

nicht so wie:

(int*) a;

Wenn Sie sich angewöhnen, den Stern neben der Variablen zu platzieren, werden Ihre Deklarationen leichter lesbar. Es vermeidet auch Schandflecken wie:

int* a[10];

— Bearbeiten —

Um genau zu erklären, was ich meine, wenn ich sage, dass es analysiert wird als int (*a)das bedeutet, dass * bindet fester an a als es tut intin sehr viel der Weise, dass im Ausdruck 4 + 3 * 7 3 bindet fester an 7 als es tut 4 aufgrund des höheren Vorrangs von *.

Mit Entschuldigung für die ASCII-Grafik, eine Zusammenfassung des AST zum Parsen int *a sieht ungefähr so ​​aus:

      Declaration
      /         \
     /           \
Declaration-      Init-
Secifiers       Declarator-
    |             List
    |               |
    |              ...
  "int"             |
                Declarator
                /       \
               /        ...
           Pointer        \
              |        Identifier
              |            |
             "*"           |
                          "a"

Wie deutlich gezeigt wird, * bindet fester an a da ihr gemeinsamer Vorfahre ist Declaratorwährend Sie den Baum bis ganz nach oben gehen müssen Declaration um einen gemeinsamen Vorfahren zu finden, der die beinhaltet int.

  • Außer const * const *const x folgt nicht der Verwendung

    – Lewis Kelsey

    14. August um 11:13 Uhr


Das ist nur eine Frage der Präferenz.

Wenn Sie den Code lesen, ist es im zweiten Fall einfacher, zwischen Variablen und Zeigern zu unterscheiden, aber es kann zu Verwirrung führen, wenn Sie sowohl Variablen als auch Zeiger eines gemeinsamen Typs in eine einzige Zeile einfügen (wovon selbst oft durch Projektrichtlinien abgeraten wird, weil die Lesbarkeit abnimmt).

Ich bevorzuge es, Zeiger mit ihrem entsprechenden Zeichen neben dem Typnamen zu deklarieren, z

int* pMyPointer;

  • Die Frage bezieht sich auf C, wo es keine Referenzen gibt.

    – Antti Haapala – Слава Україні

    1. Mai 2016 um 7:10 Uhr

  • Vielen Dank für den Hinweis, obwohl es bei der Frage nicht um Zeiger oder Referenzen ging, sondern im Grunde um die Codeformatierung.

    – Makrele

    31. Juli 2017 um 15:36 Uhr

1426190cookie-checkWarum steht das Sternchen vor dem Variablennamen und nicht nach dem Typ?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy