1845 Stimmen

Was ist der Unterschied zwischen const int*, const int * const, und int const *?

Ich bringe immer durcheinander, wie man const int* , const int * const y int const * richtig. Gibt es eine Reihe von Regeln, die festlegen, was Sie tun dürfen und was nicht?

Ich möchte wissen, was ich tun und was ich lassen soll, wenn es um Zuweisungen, die Übergabe an Funktionen usw. geht.

256 Stimmen

Sie können die "Clockwise/Spiral Rule" um die meisten C- und C++-Deklarationen zu entschlüsseln.

76 Stimmen

cdecl.org ist eine großartige Website, die automatisch C-Deklarationen für Sie übersetzt.

11 Stimmen

@Calmarius: Beginnen Sie an der Stelle, an der sich der Typenname befindet bzw. befinden sollte, gehen Sie nach rechts, wenn Sie können, und nach links, wenn Sie müssen. . int *(*)(char const * const) . Beginnen Sie rechts von der eingeklammerten * dann müssen wir nach links gehen: pointer . Außerhalb der Klammern können wir nach rechts gehen: pointer to function of ... . Dann müssen wir nach links gehen: pointer to function of ... that returns pointer to int . Wiederholen Sie den Vorgang, um den Parameter zu erweitern (die ... ) : pointer to function of (constant pointer to constant char) that returns pointer to int . Wie würde die entsprechende einzeilige Erklärung in einer leicht lesbaren Sprache wie Pascal aussehen?

2877voto

Matt Price Punkte 41298

Lesen Sie es rückwärts (wie von Uhrzeiger/Spiralregel ):

  • int* - Zeiger auf int
  • int const * - Zeiger auf const int
  • int * const - Konstante Zeiger auf int
  • int const * const - const-Zeiger auf const int

Jetzt die erste const kann also auf beiden Seiten des Typs stehen:

  • const int * == int const *
  • const int * const == int const * const

Wenn Sie richtig verrückt werden wollen, können Sie so etwas machen:

  • int ** - Zeiger auf Zeiger auf int
  • int ** const - ein Konstantenzeiger auf einen Zeiger auf einen int
  • int * const * - einen Zeiger auf einen Konstanten Zeiger auf einen int
  • int const ** - einen Zeiger auf einen Zeiger auf eine const int
  • int * const * const - einen konstanten Zeiger auf einen konstanten Zeiger auf einen int
  • ...

Und um sicherzustellen, dass wir uns über die Bedeutung von const :

int a = 5, b = 10, c = 15;

const int* foo;     // pointer to constant int.
foo = &a;           // assignment to where foo points to.

/* dummy statement*/
*foo = 6;           // the value of a can´t get changed through the pointer.

foo = &b;           // the pointer foo can be changed.

int *const bar = &c;  // constant pointer to int 
                      // note, you actually need to set the pointer 
                      // here because you can't change it later ;)

*bar = 16;            // the value of c can be changed through the pointer.    

/* dummy statement*/
bar = &a;             // not possible because bar is a constant pointer.           

foo ist ein variabler Zeiger auf eine konstante Ganzzahl. Auf diese Weise können Sie den Wert, auf den Sie zeigen, ändern, nicht aber den Wert, auf den Sie zeigen. Am häufigsten sieht man dies bei Strings im C-Stil, wo man einen Zeiger auf eine const char . Sie können die Zeichenkette, auf die Sie zeigen, ändern, aber Sie können den Inhalt dieser Zeichenketten nicht ändern. Dies ist wichtig, wenn die Zeichenkette selbst im Datensegment eines Programms liegt und nicht geändert werden soll.

bar ist eine Konstante oder ein fester Zeiger auf einen Wert, der geändert werden kann. Dies ist wie eine Referenz ohne den zusätzlichen syntaktischen Zucker. Aus diesem Grund verwenden Sie normalerweise eine Referenz, wo Sie eine T* const Zeiger, es sei denn, Sie müssen die NULL Zeigern.

608 Stimmen

Ich möchte eine Faustregel hinzufügen, die Ihnen helfen kann, sich zu erinnern, wie Sie herausfinden können, ob sich 'const' auf Zeiger oder auf spitze Daten bezieht: Teilen Sie die Anweisung am Sternchenzeichen auf, dann, wenn das const-Schlüsselwort im linken Teil erscheint (wie in 'const int * foo') - gehört es zu spitzen Daten, wenn es im rechten Teil steht ('int * const bar') - handelt es sich um den Zeiger.

26 Stimmen

@Michael: Hut ab vor Michael für eine so einfache Regel zum Erinnern/Verstehen der Konstanten Regel.

15 Stimmen

@Jeffrey: Rückwärts lesen funktioniert gut, solange es keine Klammern gibt. Dann, naja... Typedefs verwenden

555voto

Shijing Lv Punkte 5428

Für diejenigen, die Clockwise/Spiral Rule nicht kennen: Beginnen Sie mit dem Namen der Variablen, bewegen Sie sich im Uhrzeigersinn (in diesem Fall rückwärts) zur nächsten Zeiger o Typ . Wiederholen Sie dies, bis der Ausdruck endet.

Hier ist eine Demo:

pointer to int

const pointer to int const

pointer to int const

pointer to const int

const pointer to int

10 Stimmen

@Jan, der Link für das komplexe Beispiel hat keine Berechtigung. Können Sie es direkt hier posten oder die Anzeigebeschränkungen aufheben?

9 Stimmen

@Rog er hatte früher alle offenen Zugriffsrechte... Ich habe den Artikel nicht geschrieben und habe leider selbst keine Zugriffsrechte. Hier ist jedoch eine archivierte Version des Artikels, die noch funktioniert: archiv.is/SsfMX

13 Stimmen

Das komplexe Beispiel ist immer noch von rechts nach links, enthält aber die Auflösung von Klammern, wie man es normalerweise tun würde. Die ganze Sache mit der Spirale im Uhrzeigersinn macht das nicht einfacher.

190voto

Kaz Dragon Punkte 6406

Ich denke, dass hier bereits alles beantwortet wurde, aber ich möchte noch hinzufügen, dass Sie sich vor folgenden Dingen hüten sollten typedef s! Sie sind NICHT nur Textersatz.

Zum Beispiel:

typedef char *ASTRING;
const ASTRING astring;

Die Art der astring es char * const , nicht const char * . Dies ist ein Grund, warum ich immer dazu neige, die const rechts von der Schrift und nie am Anfang.

41 Stimmen

Und das ist für mich der Grund, niemals Zeiger zu typisieren. Ich sehe den Nutzen nicht in Dingen wie typedef int* PINT (Ich gehe davon aus, dass dies etwas ist, das aus der Praxis in C stammt und von vielen Entwicklern so gehandhabt wurde). Großartig, ich habe das ersetzt * mit einer P Das beschleunigt das Tippen nicht und führt zudem das von Ihnen erwähnte Problem ein.

2 Stimmen

@Mephane - Das kann ich verstehen. Allerdings scheint es mir etwas rückwärtsgewandt zu sein, ein nettes Sprachmerkmal zu vermeiden, um eine außergewöhnliche syntaktische Regel (über die "const"-Platzierung) zu verwenden, anstatt die Verwendung der außergewöhnlichen syntaktischen Regel zu vermeiden, damit man dieses Sprachmerkmal sicher nutzen kann.

11 Stimmen

@Mephane PINT ist in der Tat eine ziemlich dumme Verwendung eines typedef, vor allem weil es mich denken lässt, dass das System speichert verwendet Bier für Speicher. typedef s sind ziemlich nützlich für den Umgang mit Zeigern auf Funktionen, obwohl.

77voto

luke Punkte 34409

Wie so gut wie jeder darauf hingewiesen hat:

Was ist der Unterschied zwischen const X* p , X* const p y const X* const p ?

Sie müssen Zeigerdeklarationen lesen von rechts nach links.

  • const X* p bedeutet "p zeigt auf ein X, das const ist": das X-Objekt kann nicht über p geändert werden.

  • X* const p bedeutet "p ist ein const-Zeiger auf ein X, das non-const ist": Sie können den Zeiger p selbst nicht ändern, aber Sie können das X-Objekt über p ändern.

  • const X* const p bedeutet "p ist ein const-Zeiger auf ein X, das const ist": Sie können weder den Zeiger p selbst noch das X-Objekt über p ändern.

7 Stimmen

Vergessen Sie nicht, dass const X* p; == X const * p; wie in "p points to an X that is const": the X object can't be changed via p.

55voto

Behrooz Tabesh Punkte 1223
  1. Ständige Referenz:

    Ein Verweis auf eine Variable (hier int), die konstant ist. Wir übergeben die Variable hauptsächlich als Verweis, weil Verweise kleiner sind als der tatsächliche Wert, aber es gibt einen Nebeneffekt, nämlich den, dass sie wie ein Alias auf die tatsächliche Variable wirkt. Wir könnten die Hauptvariable durch unseren vollen Zugriff auf den Alias versehentlich ändern, also machen wir sie konstant, um diesen Nebeneffekt zu verhindern.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
  2. Konstante Zeiger

    Sobald ein konstanter Zeiger auf eine Variable zeigt, kann er auf keine andere Variable zeigen.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
  3. Zeiger auf Konstante

    Ein Zeiger, durch den man den Wert einer Variablen, auf die er zeigt, nicht ändern kann, wird als Zeiger auf eine Konstante bezeichnet.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
  4. Konstanter Zeiger auf eine Konstante

    Ein Konstantenzeiger auf eine Konstante ist ein Zeiger, der weder die Adresse, auf die er zeigt, noch den Wert, der an dieser Adresse gehalten wird, ändern kann.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X