Richtige Methode zum Deklarieren von Zeigervariablen in C / C ++ [geschlossen]

90

Ich habe festgestellt, dass einige Leute die folgende Notation zum Deklarieren von Zeigervariablen verwenden.

(a) char* p;

anstatt

(b) char *p;

Ich benutze (b). Was ist der Grund für die Notation (a)? Notation (b) ist für mich sinnvoller, da der Zeichenzeiger selbst kein Typ ist. Stattdessen ist der Typ ein Zeichen und die Variable kann ein Zeiger auf das Zeichen sein.

char* c;

Es sieht so aus, als gäbe es einen Typ char * und die Variable c ist von diesem Typ. Tatsächlich ist der Typ char und * c (der Speicherort, auf den c zeigt) ist von diesem Typ (char). Wenn Sie mehrere Variablen gleichzeitig deklarieren, wird diese Unterscheidung offensichtlich.

char* c, *d;

Das sieht komisch aus. Sowohl c als auch d sind die gleichen Zeiger, die auf ein Zeichen verweisen. Darin sieht seit dem nächsten natürlicher aus.

char *c, *d;

Vielen Dank.

Keeda
quelle
7
Was meinst du damit, dass der Zeichenzeiger kein Typ ist? Wollen Sie damit sagen, dass ein Zeiger kein Typ ist?
Benjamin Lindley
1
Ich glaube, es ist eine Frage der Präferenz, es sei denn, Sie sehen sich einen bestimmten Styleguide an (dh Ihr Unternehmen hat möglicherweise einen bestimmten Codierungsstandard, den Sie befolgen müssen). Ich neige dazu, es zwischen Wahl b und einigen in der Mitte zu verwechseln. Manchmal fühle ich mich nicht char *trichtig, also kann ich es char * t;stattdessen tun . Allerdings habe ich auch häufig gesehen char* t;.
RageD
1
Auch Ihre Argumentation "Der Typ ist char und * c (der Speicherort, auf den c zeigt) ist von diesem Typ (char)" scheint darauf hinzudeuten, dass ein Zeichen deklariert wird, obwohl dies tatsächlich nicht der Fall ist. Wenn es als solches behandelt wird, wie es manchmal von Anfängern getan wird, führt es mit Sicherheit zu Verstößen gegen den Speicherzugriff.
Benjamin Lindley
1
Beide sind immer noch ausreichend beschreibend, (b) zeigt * p ist vom Typ charund (a) zeigt p ist apointer to a char
Eine Person
1
Mit über einem Jahrzehnt Branchenerfahrung war dies heute das erste Mal, und dies nur beim Lesen von Artikeln anderer Branchenfachleute. Offensichtlich hatte ich noch nie ein religiöses Gespräch darüber, wie ich es mit Tabulatoren v Leerzeichen, Kommentaren von def oder dec oder einem der anderen Themen "Es ist gut, nichts Wichtigeres zu haben, über das man streiten kann" geführt habe . Da dies meine Perspektive ist, habe ich es so spät im Spiel meiner Karriere vorgezogen, öfter mit "char * p" zu arbeiten als nicht. Ja, Raum vor, Raum nach. Meistens, wie ich finde, reduziert es Fehler, da es den Zeiger offensichtlicher macht.
Kit10

Antworten:

102

Bjarne Stroustrup sagte:

Die Wahl zwischen "int * p;" und "int * p;" Es geht nicht um richtig und falsch, sondern um Stil und Betonung. C betonte Ausdrücke; Erklärungen wurden oft nur als notwendiges Übel angesehen. C ++ hingegen legt großen Wert auf Typen.

Ein "typischer C-Programmierer" schreibt "int * p;" und erklärt es "* p ist das, was das int ist", wobei die Syntax betont wird, und kann auf die C- (und C ++) Deklarationsgrammatik verweisen, um für die Richtigkeit des Stils zu argumentieren. In der Tat bindet das * an den Namen p in der Grammatik.

Ein "typischer C ++ - Programmierer" schreibt "int * p;" und erklärt es "p ist ein Zeiger auf einen int", der den Typ hervorhebt. In der Tat ist der Typ von p int *. Ich bevorzuge diese Betonung eindeutig und sehe sie als wichtig an, um die fortgeschritteneren Teile von C ++ gut zu nutzen.

Quelle: http://www.stroustrup.com/bs_faq2.html#whitespace

Ich würde den letzteren Stil empfehlen, da Sie in der Situation, in der Sie mehrere Zeiger in einer einzigen Zeile deklarieren (Ihr viertes Beispiel), das Sternchen mit der Variablen gewohnt sind.

BlackJack
quelle
34
Andere empfehlen, niemals mehrere Objekte in derselben Deklaration zu deklarieren. :-)
Bo Persson
5
Ich betone die Logik hinter der Syntax, daher bevorzuge ich : int *p, was bedeutet: Wenn pdereferenziert wird, bekomme ich eine int. Dann werden mehrere Deklarationen durch getrennt, Sinn: int *p, *q, r(wenn poder qdereferenziert wird, bekomme ich eine int, wenn rreferenziert wird, bekomme ich eine int). Auch die Funktionszeigersyntax ist sinnvoll: int (*f)()(wenn fdereferenziert und aufgerufen wird, bekomme ich eine int). Und das macht Sinn : int *p, (*f)().
Druesukker
2
Dies half mir zu erkennen, dass die andere Seite des Arguments Gültigkeit hat. Da ich hauptsächlich ein hochrangiger Programmierer bin, betone ich den Typ; und bevorzugen int*. Für mich int *p, (*f)()macht das nicht viel Sinn, aber ich kann sehen, wie es für manche Menschen in bestimmten Situationen wäre.
Assimilater
1
@Druesukker, deine Aussage ist sinnvoller als jede der oben genannten, denke ich.
Muntashir Akon
1
@Druesukker Aber die Logik funktioniert nicht genau für void*(und überhaupt nicht für C ++ - Referenzen).
Jamesdlin
57

Ich persönlich bevorzuge es, das *mit dem Rest des Typs zu platzieren

char* p;  // p is a pointer to a char.

Die Leute werden argumentieren "aber dann char* p, q;wird es irreführend", zu dem ich sage, "also tu das nicht".

Ikegami
quelle
Sehr gutes Argument für das Zeichen * p; Wahl :) Ich habe nichts dagegen, solange es nicht schwer zu lesen ist, wie das Beispiel, das Sie gezeigt haben. In diesem Fall sollten sie das nicht tun.
Jesus Ramos
1
Und wann möchten Sie den Wert ausgeben? Das tust du cout << *p;. Warum also nicht den Stern während der Deklaration vorher setzen p: *p? Meiner Meinung nach wäre es weniger verwirrend.
user1170330
13
@ user1170330, weil es an einer Stelle Teil der Typdefinition ist und an der anderen Stelle ein Dereferenzierungsoperator. Keine Beziehung. Wenn überhaupt, ist es gut, dass sie anders aussehen, da verschiedene Dinge anders aussehen sollten.
Ikegami
32

Es gibt keinen Unterschied, wie man schreibt. Wenn Sie jedoch zwei oder mehr Zeiger in einer Zeile deklarieren möchten, verwenden Sie besser die Variante (b), da klar ist, was Sie möchten. Schauen Sie unten:

int *a;
int* b;      // All is OK. `a` is pointer to int ant `b` is pointer to int
char *c, *d; // We declare two pointers to char. And we clearly see it.
char* e, f;  // We declare pointer `e` and variable `f` of char type.
             // Maybe here it is mistake, maybe not. 
// Better way of course is use typedef:
typedef char* PCHAR;
PCHAR g, h;  // Now `g` and `h` both are pointers.
// If we used define construction for PCHAR we'd get into problem too.
George Gaál
quelle
5
typedefist "natürlich" kein besserer Weg. Einige Leute bevorzugen es vielleicht, aber es ist problematisch, wenn mehrere Personen mit Ihrem Code arbeiten. Wenn ich nicht daran gewöhnt PCHARbin, könnte ich so etwas schreiben PCHAR *p;, was ein char**und nicht das ist, was ich beabsichtige. Wenn Sie einen möchten char**, müssen Sie im Allgemeinen PCHAR*einen neuen Typ schreiben oder definieren, und dann wird er einfach nur dumm.
BlackJack
3
Wenn Sie einen komplexen Zeigertyp benötigen, z. B. einen Zeiger, um zu funktionieren, ist es eine sehr gute Idee, typedefs zu erstellen. Sie machen Code in diesem Fall viel einfacher. Andererseits ist die Verwendung von PCHAR ein synthetischeres Beispiel als die tägliche Praxis. Aber es macht klar, was Sie wollen. und dann wird es einfach nur dumm Bitte richten Sie alle Beschwerden an Stroustrup :-)
George Gaál
Wenn Sie PCHAR * p geschrieben haben, um einen Zeiger auf char zu definieren, ist es offensichtlich, dass Sie nicht wissen, was Sie tun, und den Typ def nicht gelesen haben. Die Antwort ist seiner Meinung nach. Das typedef bietet noch einen weiteren Vorteil. In C geht es darum, Dinge auf einfache Weise undurchsichtig zu machen. öffentlich das Symbol als VOID ptr definiert haben, privat ist der Typ def etwas anderes .... Ich würde lieber ab und zu ein typedef anpassen und dann alles im gesamten Code anpassen, wenn wir etwas an einem der Typen ändern ... aber C ++ 11 adressiert viel davon mit Autos
UpAndAdam
Für jemanden, der nur versucht, fünf Jahre nach dem College wieder mit C ++ zu spielen, ist dies eine der besten Antworten.
Panzercrisis
10

Der Kompromiss ist

char * p;

K & R verwendet

char *p;

Es liegt an Ihnen, es sei denn, Sie folgen einem Codierungsstandard. In diesem Fall sollten Sie den Anweisungen aller anderen folgen.

jnnnnn
quelle
4
Ich habe auf die harte Tour gelernt, dass char * x, y nicht bedeutet, dass y ein char * ist. Jetzt kann ich sehen, warum K & R diesem Stil folgt.
Rahul Kadukar
Was ist K & R und warum ist es wichtig, was eine einzelne Codequelle verwendet? Ich benutze char* p;. Es ist eine Frage des Stils, nicht der Konvention oder der Regeln. Für mich ist es sinnvoller, dass p vom Typ ist char*, daher sollte das * offensichtlich mit dem Typ sein.
FalcoGer
@ FalcoGer Ich habe einen Link für K & R hinzugefügt. Es spielt keine Rolle, was eine einzelne Codequelle verwendet. Ihr Team könnte sich über Sie ärgern, wenn Sie ihren Standard nicht befolgen, weil Sie dafür sorgen, dass sie härter arbeiten, um Ihren Code zu verstehen. In diesen Tagen würde ich hoffen, dass Teams clang-formatsowieso verwenden.
jnnnnn
2

Es ist alles eine Frage der Präferenz, persönlich bei Projekten, bei denen ich das Zeichen * sehe. Ich neige dazu, mehrere Zeiger in separaten Zeilen zu deklarieren. Es gibt keinen wirklichen "richtigen" Weg, dies zu tun, und alles hängt von den Vorlieben ab. Einige sagen, es sei einfacher, (a) zu lesen, während andere sagen, dass (b) es einfacher ist, mehr Variablen desselben Typs in derselben Zeile zu deklarieren.

Ich finde (b) häufiger, und in einigen Fällen habe ich gesehen

char * a;

oder sowas. Wieder Präferenz. Was auch immer Sie mögen oder was auch immer das Projekt, an dem ich arbeite, verwendet, ich werde es verwenden (es sei denn, ich schreibe es selbst. In diesem Fall verwende ich (a)).

Jesus Ramos
quelle