const char * und char const * - sind sie gleich?

81

Nach meinem Verständnis sollten constModifikatoren von rechts nach links gelesen werden. Daraus ergibt sich:

const char*

ist ein Zeiger, dessen char-Elemente nicht geändert werden können, der Zeiger selbst jedoch und

char const*

ist ein konstanter Zeiger auf mutableZeichen.

Aber ich bekomme die folgenden Fehler für den folgenden Code:

const char* x = new char[20];
x = new char[30];   //this works, as expected
x[0] = 'a';         //gives an error as expected

char const* y = new char[20];
y = new char[20];   //this works, although the pointer should be const (right?)
y[0] = 'a';         //this doesn't although I expect it to work

Also ... welches ist es? Ist mein Verständnis oder mein Compiler (VS 2005) falsch?

Luchian Grigore
quelle
35
Verwenden Sie im Zweifelsfall immer die Spiralregel .
Alok Save
"... dessen char-Elemente geändert werden können, aber der Zeiger selbst kann und ..." - Ich denke, Sie wollten für eine dieser "Dosen" "nicht" sagen, aber ich weiß nicht wie Ich bin verwirrt, also weiß ich nicht, was ich korrigieren soll: P
Detly
1
Versuchen Sie diese Website: www.cdecl.org
yasouser
Compiler ist nie falsch;)
Monolith

Antworten:

129

constÄndert das Element gemäß dem Standard direkt links davon . Die Verwendung constzu Beginn einer Erklärung ist nur eine bequeme mentale Abkürzung. Die folgenden zwei Aussagen sind also äquivalent:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

Um sicherzustellen, dass der Zeiger selbst nicht geändert wird, constsollte nach dem Sternchen gesetzt werden:

char * const constantPointerToMutableContent;

Verwenden Sie zwei Konstanten, um sowohl den Zeiger als auch den Inhalt zu schützen, auf den er zeigt.

char const * const constantPointerToConstantContent;

Ich habe mich immer persönlich verabschiedet mich dafür entschieden, die Konstante nach dem Teil zu setzen, den ich nicht ändern möchte, damit ich die Konsistenz behalte, auch wenn der Zeiger der Teil ist, den ich konstant halten möchte.

Greyson
quelle
23
'bequeme Kurzschrift' ist eine interessante Beschreibung für etwas, das nicht kürzer ist und nicht den normalen Regeln folgt.
Beetstra
Dem Standard ist es egal, welche Reihenfolge Sie verwenden. Abschnitt 7.1.6 zeigt nur beide Stellen und sagt, dass Sie sie nur an einer Stelle verwenden sollen.
edA-qa mort-ora-y
1
@ Beetstra Ich stimme zu. Ich habe es in "bequeme mentale Abkürzung" geändert, um etwas klarer zu sein.
Greyson
31

Es funktioniert, weil beide gleich sind. Vielleicht bist du darin verwirrt,

const char*  // both are same
char const*

und

char* const  // unmutable pointer to "char"

und

const char* const  // unmutable pointer to "const char"

[Um sich daran zu erinnern, hier ist eine einfache Regel: '*' wirkt sich zuerst auf die gesamte LHS aus. ]

iammilind
quelle
Ok, ich habe es jetzt verstanden. Danke vielmals.
Luchian Grigore
1
unmutable pointer to char*Es ist ein unveränderlicher Zeiger, der auf charnicht zeigt char *.
Alok Save
25

Das liegt daran, dass die Regel lautet:

REGEL: constbindet links, es sei denn, links ist nichts, dann bindet es rechts :)

Betrachten Sie diese als:

(const --->> char)*
(char <<--- const)*

beide gleich! Oh, und --->>und <<---sind KEINE Operatoren, sie zeigen nur, woran die constBindungen bestehen.

Akanksh
quelle
2
Ja, der richtige Operator ist -->>und er arbeitet nur mit Werten. Versuchen Sie int i = 8; std::cout << (i -->> 1) << std::endl;:)
Alexander Malakhov
11

(aus 2 einfachen Fragen zur Variableninitialisierung )

Eine wirklich gute Faustregel in Bezug auf const:

Lesen Sie die Erklärungen von rechts nach links.

(siehe Vandevoorde / Josutiss "C ++ - Vorlagen: Das vollständige Handbuch")

Z.B:

int const x; // x is a constant int
const int x; // x is an int which is const

// easy. the rule becomes really useful in the following:
int const * const p; // p is const-pointer to const-int
int const &p;        // p is a reference to const-int
int * const * p;     // p is a pointer to const-pointer to int.

Seit ich diese Faustregel befolge, habe ich solche Erklärungen nie wieder falsch interpretiert.

(: sisab retcarahc-rep a no ton, sisab nekot-rep a no tfel-ot-thgir naem I hguohT: tidE

Sebastian Mach
quelle
+1 Das ist fantastisch, danke! Ich habe seit const char* constEwigkeiten versucht, mich mit Dingen wie zu beschäftigen, und dank dir verstehe ich es jetzt.
OMGtechy
5

So versuche ich immer zu interpretieren:

char *p

     |_____ start from the asterisk. The above declaration is read as: "content of `p` is a `char`".

char * const p

     |_____ again start from the asterisk. "content of constant (since we have the `const` 
            modifier in the front) `p` is a `char`".

char const *p

           |_____ again start from the asterisk. "content of `p` is a constant `char`".

Ich hoffe es hilft!

yasouser
quelle
0

In beiden Fällen zeigen Sie auf ein konstantes Zeichen.

const char * x  //(1) a variable pointer to a constant char
char const * x  //(2) a variable pointer to a constant char
char * const x  //(3) a constant pointer to a variable char
char const * const x //(4) a constant pointer to a constant char
char const * const * x //(5) a variable pointer to a constant pointer to a constant char
char const * const * const x //(6) can you guess this one?

constGilt standardmäßig für das, was unmittelbar links ist, aber es kann auch für das gelten, was unmittelbar rechts davon ist, wenn nichts davor steht, wie in (1).

Lino Mediavilla
quelle
Letzter: Ein konstanter variabler Zeiger auf einen konstanten Zeiger auf ein konstantes Zeichen.
Secko
Wenn Sie mit "konstanter variabler Zeiger" "konstanter Zeiger" meinen, dann haben Sie es geschafft, Bruder!
Lino Mediavilla
Nun, in (5) ist das ein variabler Zeiger auf einen konstanten Zeiger auf ein konstantes Zeichen, einfach weil es rechts vom letzten Stern vor dem Bezeichner "x" kein "const" gibt. Aber in (6) wird das ein konstanter Zeiger, der Rest bleibt gleich.
Lino Mediavilla