2010-07-19 9 views
16

Ich erinnere mich vage daran, das vorher in einer Antwort auf eine andere Frage gesehen zu haben, aber das Suchen hat nicht die Antwort ergeben.In C, was ist die richtige Syntax zum Deklarieren von Zeigern?

Ich kann mich nicht erinnern, was der richtige Weg ist, Variablen zu deklarieren, die Zeiger sind. Ist es:

Type* instance; 

Oder:

Type *instance; 

Obwohl ich weiß, beide in den meisten Fällen kompilieren, ich glaube, es gibt einige Beispiele, bei denen es wichtig ist, möglicherweise im Zusammenhang mit mehreren Variablen des gleichen Typs deklarieren auf der gleichen Linie, und so macht man mehr Sinn als die andere.

+0

mögliche Duplikate von [Zeigerdeklarationen in C++: Platzierung des Sternchens] (http://stackoverflow.com/questions/180401/pointer-declarations-in-cplacement-of-the-asterisk) – Qadi

Antwort

21

Es ist einfach eine Frage, wie Sie wollen, es zu lesen.

Der Grund, dass manche Leute es so:

Type *instance; 

ist, weil er sagt, dass nur Beispiel ein Zeiger ist. Denn wenn Sie eine Liste von Variablen haben:

int* a, b, c; 

Nur ein Zeiger, so ist es einfacher, wie so

int *a, b, c, *d; 

Wo a und d-Zeiger sind. Es macht eigentlich keinen Unterschied, es geht nur um Lesbarkeit.

Andere Leute mögen das * neben dem Typ haben, weil sie es (neben anderen Gründen) als "Zeiger auf eine Ganzzahl" betrachten und denken, dass das * zum Typ gehört, nicht zur Variablen.

Ich persönlich tue immer

Type *instance; 

Aber es ist wirklich an Ihnen und Ihrem Unternehmen/Schule Code-Stil-Richtlinien.

+0

Das war es, denke ich. Es war das Deklarieren mehrerer Variablen in einer Zeile, und ich konnte mich nicht erinnern, ob der Compiler "Type *" als Typ behandelt hat, oder ob das * eher wie ein Modifikator für eine Variable war, der angibt, dass es sich um einen Zeiger auf eine Instanz des Typs handelte "Art". 'int * a, b, c' würde mich verwirren, also werde ich' Type * instance' verwenden, wenn es keine anderen Richtlinien gibt. – Edd

+0

Ich benutze 'int *' in C und 'int *' in C++. In C++ ist es allgemein üblich, Bezeichner einzeln zu deklarieren, so dass das Argument "int * a, b, c fluffy" weniger aussagekräftig ist. Die Typsystemkonsistenz ist im C++ Fall ein wichtiges Thema. –

3

Diese beiden sind genau gleich.

jedoch für die Zwecke der mehrere Variablen deklarieren, wie in unten:

int * p1, p2; 

wobei P1 vom Typ Zeiger auf int, aber p2 ist vom Typ Int. Wenn Sie p2 als Zeiger erklären wollte int, müssen Sie schreiben:

int *p1, *p2; 
+0

Das stimmt , in der Ein-Deklaration, die das OP hat, aber nicht im allgemeinen Fall. – Puppy

+0

@DeadMG: das ist richtig, bearbeitet, um zu klären. –

10

Diese beiden sind gleich. Wenn Sie jedoch mehrere Deklarationen durchführen, können Sie mit der ersten Meldung auftauchen.

int* pi, j;

deklariert einen int Zeiger (pi) und einen int (j).

1

Seltsamerweise gilt diese Regel nicht, wenn der Typ in C++ 0x abgeleitet wird.

int a; 
decltype(&a) i, j; 

Sowohl i als auch j sind int *.

+2

Ich glaube nicht, dass Sie C++ 0x für ein solches Verhalten benötigen. Einfach ein 'typedef int * IntPtr;', dann 'IntPtr i, j;' zeigt das gleiche Verhalten. – Philipp

2

Ich ziehe den folgenden Stil:

Type *pointer; 

Warum? Weil es mit der Denkweise konsistent ist, versuchten die Ersteller der Sprache festzustellen:

"Die Syntax der Deklaration für eine Variable ahmt die Syntax von Ausdrücken, in denen die Variable angezeigt werden könnte."

(The C Programming Language von Brian W. Kernighan & Dennis M. Ritchie, ansi c Version, Seite 94)

Es ist einfach, Fortran in jeder Sprache zu schreiben, aber Sie sollten immer schreiben [Programmiersprache X] in [Programmiersprache X].

6

Es ist ein Zufall der C-Syntax, dass Sie es in beide Richtungen schreiben können; jedoch wird es immer als

analysiert
Type (*pointer); 

das heißt, ist die * immer auf die declarator gebunden ist, nicht der Programmtyp. Wenn Sie

schrieb
Type* pointer1, pointer2; 

es würde als

Type (*pointer1), pointer2; 

so nur Zeiger1 als Zeigertyp würde deklariert werden analysiert werden.

C folgt einem "declaration mimics use" -Paradigma; Die Struktur einer Deklaration sollte den äquivalenten Ausdruck, der im Code verwendet wird, so weit wie möglich nachahmen. Wenn Sie z. B. ein Array mit Zeigern auf int mit dem Namen arr haben und den Ganzzahlwert abrufen möchten, auf den das i-te Element im Array zeigt, würden Sie das Array subskribieren und das Ergebnis dereferenzieren, das als *arr[i] geschrieben wird (geparst als *(arr[i])). Der Typ des Ausdruck*arr[i] ist int, so die Erklärung für arr als

geschrieben
int *arr[N]; 

Welche Weise ist Recht? Kommt drauf an, wen du fragst. Old C farts gefällt mir gefällt T *p, weil es widerspiegelt, was tatsächlich in der Grammatik passiert. Viele C++ Programmierer favorisieren T* p, weil es den Typ betont, der sich in vielen Situationen natürlicher anfühlt (nachdem ich meine eigenen Containertypen geschrieben habe, kann ich den Punkt sehen, obwohl es sich immer noch falsch anfühlt).

Wenn Sie mehrere Zeiger deklarieren möchten, können Sie entweder erklären sie alle explizit, wie zum Beispiel:

T *p1, *p2, *p3; 

oder Sie können eine typedef erstellen:

typedef T *tptr; 
tptr p1, p2, p3; 

obwohl ich persönlich nicht tun empfiehl es; Das Verbergen der Zeiger-Eigenschaft von etwas hinter einem Typdef kann dich beißen, wenn du nicht vorsichtig bist.

+0

Das Verbergen der Pointer-Ness von etwas mit einem Typedef kann sehr praktisch sein, wenn Sie Smart Pointer verwenden. Das Schreiben von 'MyClassPtr' ist viel schneller als' boost :: shared_ptr 'zum Beispiel. –

+0

Es ist auch eine Nervensäge, wenn Sie mehrere hundert Zeilen der Vorlagediagnose durchforsten müssen, weil ein Iterator nicht richtig dereferenziert wird; dh, Sie sollten '(* it) -> foo()' anstelle von 'it-> foo()' schreiben, aber weil der Iterator als 'vector :: iterator' statt' deklariert wurde Vektor :: Iterator ", Sie haben nicht bemerkt, dass die zusätzliche Dereferenzierung notwendig war. Das war nicht der produktivste Nachmittag. –

0

Als eine Nebenbemerkung, ich denke, es hilft, die Motivation hinter der C-Deklaration Syntax zu verstehen, die imitieren soll, wie die Variable verwendet werden könnte.Einige Beispiele unter:

  • char *x bedeutet, dass, wenn Sie *x tun Sie eine char bekommen.
  • int f(int x) bedeutet, dass, wenn Sie z.B. f(0), erhalten Sie eine int.
  • const char *foo[3] bedeutet, dass, wenn Sie z.B. *foo[0] (das ist das gleiche wie *(foo[0])), erhalten Sie eine const char. Dies impliziert, dass foo ein Array (in diesem Fall der Größe 3) von Zeigern zu const char sein muss.
  • bedeutet, dass, wenn Sie z.B. (*foo)[0], erhalten Sie eine unsigned int. Dies bedeutet, dass foo ein Zeiger auf ein Array von unsigned int (in diesem Fall der Größe 3) sein muss.

Lose ist die allgemeine Syntax daher [what you get] [how you get it]. Der Trick ist, dass dies auf [what you get] [how you get it], [how you get it], ... erweitert werden kann, um mehrere Dinge gleichzeitig zu deklarieren. Daher werden die folgenden drei Erklärungen -

int *p; 
int f(int x); 
int a[3]; 

- kann in einer einzigen Zeile wie folgt kombiniert werden (und ja, das funktioniert auch für Funktionsdeklarationen Sie sind in dieser Hinsicht nicht besonders.):

int *p, f(int x), a[3]; 
1

Alle diese kompilieren, rechtmäßig und sind äquivalent:

Type* instance; 
Type * instance; 
Type *instance; 

einen Stil-Auswahl und konsistent sein.

Verwandte Themen