wake-up-neo.com

Unterschied zwischen char * und const char *?

Was ist der Unterschied zwischen 

char* name

was auf ein konstantes String-Literal verweist, und 

const char* name
143
Iceman

char* ist ein veränderbarer Zeiger auf einen veränderbaren Zeichen/String.

const char* ist ein veränderbarer Zeiger auf eine unveränderliche Zeichen/Zeichenfolge. Sie können den Inhalt der Orte, auf die dieser Zeiger zeigt, nicht ändern. Außerdem müssen Compiler Fehlermeldungen eingeben, wenn Sie dies versuchen. Aus demselben Grund wird die Konvertierung von const char * in char* nicht mehr unterstützt.

char* const ist ein unveränderlicher Zeiger (er kann nicht auf einen anderen Ort verweisen) aber der Inhalt des Ortes, auf den er verweist - mutierbar .

const char* const ist ein unveränderlicher Zeiger auf eine unveränderliche Zeichen/Zeichenfolge.

325
ankit.karwasra
char *name

Sie können das Zeichen ändern, auf das name zeigt, und auch das Zeichen, auf das es zeigt.

const char* name

Sie können das Zeichen ändern, auf das name zeigt, aber Sie können das Zeichen, auf das es zeigt, nicht ändern.
Korrektur: Sie können den Zeiger ändern, aber nicht das Zeichen, auf das name zeigt ( https://msdn.Microsoft .com/de-de/library/vstudio/whkd4k6a (v = vs.100) .aspx , siehe "Beispiele"). In diesem Fall gilt der const-Spezifizierer für char, nicht für das Sternchen.

Gemäß der MSDN-Seite und http://en.cppreference.com/w/cpp/language/declarations ist die const vor dem * Teil der Deklarationsspezifizierer-Sequenz, während die const nach * ein Teil von ist der deklarator. 
Eine Deklarationsbezeichnersequenz kann von mehreren Deklaratoren gefolgt werden, weshalb const char * c1, c2c1 als const char * und c2 als const char deklariert.

EDIT:

In den Kommentaren scheint Ihre Frage nach dem Unterschied zwischen den beiden Deklarationen zu fragen, wenn der Zeiger auf ein String-Literal zeigt. 

In diesem Fall müssen Sie sollte nicht das Zeichen ändern, auf das name zeigt, da dies zu Undefined Behavior..__ führen kann. String-Literale können in schreibgeschützten Speicherbereichen (Implementierung) zugewiesen werden definiert) und ein Benutzerprogramm sollte es in keiner Weise ändern. Jeder Versuch führt dazu undefiniertes Verhalten. 

Der einzige Unterschied in diesem Fall (der Verwendung mit String-Literalen) besteht also darin, dass die zweite Deklaration Ihnen einen leichten Vorteil verschafft. Compiler geben normalerweise eine Warnung aus, falls Sie versuchen, das String-Literal im zweiten Fall zu ändern.

Online-Beispielbeispiel:

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

Ausgabe: 

cc1: Warnungen, die als Fehler behandelt werden
prog.c: In der Funktion 'main':
prog.c: 9: Fehler: Durch das Übergeben von Argument 1 von "strcpy" werden Qualifizierer vom Zeigerzieltyp verworfen 

Beachten Sie, dass der Compiler für den zweiten Fall warnt, nicht jedoch für den ersten.

41
Alok Save
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)

constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error

constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok

// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok
15
Afriza N. Arief

In keinem Fall können Sie ein String-Literal ändern, unabhängig davon, ob der Zeiger auf dieses String-Literal als char * oder const char * deklariert ist.

Der Unterschied besteht jedoch darin, dass der Compiler, wenn der Zeiger const char * ist, eine Diagnose abgeben muss, wenn Sie versuchen, den angegebenen Wert zu ändern. Wenn der Zeiger char * ist, ist dies jedoch nicht der Fall.

9
caf

Das erste können Sie tatsächlich ändern, wenn Sie möchten, das zweite können Sie nicht. Informieren Sie sich über const-Korrektheit. Es gibt auch char const * name, wo Sie es nicht neu festlegen können.

2
chikuba

FALL 1:

char *str = "Hello";
str[0] = 'M'  //No warning or error, just Undefined Behavior

Das obige setzt str so, dass es auf den Literalwert "Hello" verweist, der im Binärbild des Programms, das im Speicher als schreibgeschützt gekennzeichnet ist, hartcodiert ist, bedeutet, dass jede Änderung dieses String-Literal ungültig ist und Segmentierungsfehler verursacht.

FALL 2:

const char *str = "Hello";
str[0] = 'M'  //Compiler issues a warning

FALL 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
2
Mohit

Tatsächlich ist char* name kein Zeiger auf eine Konstante, sondern ein Zeiger auf eine Variable. Sie sprechen vielleicht über diese andere Frage.

Was ist der Unterschied zwischen char * const und const char *?

1
Jeff Wolski

Die Frage ist, worin der Unterschied besteht

char *name

was auf ein konstantes String-Literal verweist, und

const char *cname

D.h. gegeben 

char *name = "foo";

und

const char *cname = "foo";

Es gibt keinen großen Unterschied zwischen den beiden und beide können als richtig angesehen werden. Aufgrund des langen Erbes von C-Code hatten die String-Literale den Typ char[] und nicht const char[]. Außerdem gibt es viele ältere Codes, die ebenfalls char * anstelle von const char * akzeptieren, auch wenn sie die Argumente nicht ändern. 

Der Hauptunterschied der 2 ist im Allgemeinen, dass *cname oder cname[n] zu lWerten des Typs const char ausgewertet wird, während *name oder name[n] zu lWerten des Typs char ausgewertet wird, die modifizierbare lWerte sind. Ein konformer Compiler ist erforderlich, um eine Diagnosemeldung zu erzeugen, wenn das Ziel der Zuweisung kein veränderbarer Wert ist ; es muss keine Warnung bei der Zuordnung zu Werten vom Typ char ausgegeben werden:

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message

Der Compiler ist nicht required, um die Kompilierung in beiden Fällen zu stoppen. es reicht aus, dass es eine warning für die Zuordnung zu cname[0] erzeugt. Das resultierende Programm ist kein correct - Programm. Das Verhalten des Konstrukts ist undefined. Es kann abstürzen oder, was noch schlimmer ist, es kann nicht abstürzen und das Zeichenfolgenliteral im Speicher ändern.

1
Antti Haapala

Um nur ein Beispiel zu nennen: 

    std::cout << typeid(2.3).name() << '\n'; // -----> prints "double" simply because
    //2.3 is a double
    //But the "double" returned by typeid(2.3).name() is indeed a 
    //const char * which consists of 'd','o','u','b','l','e'and'\0'.
    //Here's a simple proof to this:
    std::cout << typeid(typeid(2.3).name()).name() << '\n'; //prints: "const char *"
    const char* charptr
    charptr = typeid(2.3).name();
    std::cout << charptr[3]; // --------->  prints: "b"

(Ich verwende die typeinfo-Bibliothek: http://www.cplusplus.com/reference/typeinfo/type_info/name )

    //Now let's do something more interesting:
    char* charptr2="hubble";
    strcpy(charptr, charptr2);  // --------> Oops! Sorry, this is not valid!

Sie können es ausführen und die Dinge für sich selbst besser sehen.

0
M-J