Was ist der Unterschied zwischen
char* name
was auf ein konstantes String-Literal zeigt, und
const char* name
Was ist der Unterschied zwischen
char* name
was auf ein konstantes String-Literal zeigt, und
const char* name
Antworten:
char*
ist ein veränderbarer Zeiger auf ein veränderliches Zeichen / eine veränderbare Zeichenfolge.
const char*
ist ein veränderbarer Zeiger auf ein unveränderliches Zeichen / eine unveränderliche Zeichenfolge. Sie können den Inhalt der Position (en), auf die dieser Zeiger zeigt, nicht ändern. Außerdem müssen Compiler Fehlermeldungen ausgeben, wenn Sie dies versuchen. Aus dem gleichen Grund ist die Umstellung von const char *
auf char*
veraltet.
char* const
ist ein unveränderlicher Zeiger (er kann nicht auf einen anderen Ort zeigen), aber der Inhalt des Ortes, auf den er zeigt, ist veränderlich .
const char* const
ist ein unveränderlicher Zeiger auf ein unveränderliches Zeichen / eine unveränderliche Zeichenfolge.
char const *
char *
beim Ausführen keinen Segmentierungsfehler verursachen?
const
wenn ich möchte, dass der Compiler einen Fehler macht, wenn ich die Daten versehentlich vergessen und geändert habe, oder?
char *name
Sie können das Zeichen ändern, auf das gezeigt wird name
, und auch das Zeichen, auf das es zeigt.
const char* name
Sie können das Zeichen auf welche name
Punkte ändern, 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
verweist ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , siehe "Beispiele"). ). In diesem Fall gilt der const
Bezeichner fürchar
und nicht das Sternchen.
Gemäß der MSDN - Seite und http://en.cppreference.com/w/cpp/language/declarations , die const
vor dem *
Teil der Decl-Spezifikationsfolge, während der const
nach *
Teil des declarator ist.
Auf eine Deklarationsspezifiziererfolge können mehrere Deklaratoren folgen, weshalb as und as const char * c1, c2
deklariert werdenc1
const char *
c2
const char
.
BEARBEITEN:
Aus den Kommentaren geht hervor, dass Ihre Frage nach dem Unterschied zwischen den beiden Deklarationen fragt, wenn der Zeiger auf ein Zeichenfolgenliteral zeigt.
In diesem Fall Sie sollten nicht das Zeichen , auf die ändern name
Punkte, wie es in Folge konnte nicht definiertes Verhalten . String-Literale können in schreibgeschützten Speicherbereichen zugewiesen werden (Implementierung definiert), und ein Benutzerprogramm sollte sie ohnehin nicht ändern. Jeder Versuch, dies zu tun, führt zu undefiniertem Verhalten.
Der einzige Unterschied in diesem Fall (bei Verwendung mit String-Literalen) besteht darin, dass die zweite Deklaration Ihnen einen leichten Vorteil verschafft. Compiler geben normalerweise eine Warnung aus, wenn Sie im zweiten Fall versuchen, das Zeichenfolgenliteral zu ändern.
#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 werden als Fehler behandelt
prog.c: In Funktion 'main':
prog.c: 9: Fehler: Übergabe von Argument 1 von 'strcpy' verwirft Qualifizierer vom Zeigerzieltyp
Beachten Sie, dass der Compiler für den zweiten Fall warnt, nicht jedoch für den ersten.
name
Zeichen, auf das die Punkte zeigen, in beiden Fällen nicht ändern. Dies könnte zu UB führen.
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
char *
Werts einen Segmentierungsfehler verursacht, da wir versuchen, ein Zeichenfolgenliteral zu ändern (das im Nur-Lese-Speicher vorhanden ist)
In keinem Fall können Sie ein Zeichenfolgenliteral ändern, unabhängig davon, ob der Zeiger auf dieses Zeichenfolgenliteral als char *
oder deklariert ist const char *
.
Der Unterschied besteht jedoch darin, dass const char *
der Compiler eine Diagnose geben muss, wenn Sie versuchen, den Zeigerwert zu ändern. Wenn der Zeiger dies ist, char *
ist dies jedoch nicht der Fall.
extern ... name
und haben *name = 'X';
. Auf einem 'richtigen Betriebssystem' könnte dies fehlschlagen, aber auf eingebetteten Systemen würde ich erwarten, dass es etwas Plattform- / Compilerspezifisches tut.
FALL 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Die obigen Sätze str zeigen auf den Literalwert "Hello", der im Binärbild des Programms fest codiert ist und im Speicher als schreibgeschützt gekennzeichnet ist. Dies bedeutet, dass jede Änderung in diesem String-Literal unzulässig ist und Segmentierungsfehler verursachen würde.
FALL 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
Fall 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Das erste können Sie tatsächlich ändern, wenn Sie möchten, das zweite können Sie nicht. Informieren Sie sich über die const
Richtigkeit (es gibt einige nette Anleitungen zum Unterschied). Es gibt auch char const * name
Stellen, an denen Sie es nicht neu festlegen können.
Die Frage ist, was der Unterschied zwischen ist
char *name
was auf ein konstantes String-Literal zeigt, und
const char *cname
Dh gegeben
char *name = "foo";
und
const char *cname = "foo";
Es gibt keinen großen Unterschied zwischen der 2 und beide können als richtig angesehen werden. Durch die lange Tradition von C - Code haben die Stringliterale eine Art hatten char[]
, nicht const char[]
, und es gibt viele älteren Code, der ebenfalls akzeptieren char *
statt const char *
, auch wenn sie die Argumente nicht ändern.
Der Hauptunterschied der 2 im Allgemeinen besteht darin, dass *cname
oder cname[n]
wird zu l-Werten des Typs ausgewertet const char
, wohingegen *name
oder name[n]
zu l-Werten des Typs ausgewertet wird char
, die modifizierbare l-Werte sind . Ein konformer Compiler muss eine Diagnosemeldung erstellen, wenn das Ziel der Zuweisung kein veränderbarer Wert ist . Bei der Zuordnung zu lWerten des Typs muss keine Warnung ausgegeben werden char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
Der Compiler ist nicht erforderlich , die Zusammenstellung in jedem Fall zu stoppen; es reicht aus, dass es eine Warnung für die Zuordnung zu erzeugt cname[0]
. Das resultierende Programm ist kein korrektes Programm. Das Verhalten des Konstrukts ist undefiniert . Es kann abstürzen oder noch schlimmer, es kann nicht abstürzen und das String-Literal im Speicher ändern.
Eigentlich char* name
ist es kein Zeiger auf eine Konstante, sondern ein Zeiger auf eine Variable. Sie könnten über diese andere Frage sprechen.
Was ist der Unterschied zwischen char * const und const char *?