Frage Was ist der Unterschied zwischen char * und int * -Datentyp, um ein Array von Zeigern in C ++ zu erstellen?


Beim Erstellen eines Arrays von Zeigern für int Datentyp der folgende Code funktioniert:

int var[] = {10, 100, 200, 1000};
int *ptr[] = {&var[0], &var[1], &var[2], &var[3]};

Beim Erstellen eines Arrays von Zeigern für char Datentyp Folgendes ist legal:

char *names[] = {"Mathew Emerson", "Bob Jackson"};

Aber wenn ich ein Array von Zeigern für erstellen int Datentyp wie folgt:

int var[] = {10, 100, 200, 1000};
int *ptr[] = {var[0], var[1], var[2], var[3]};

Ich bekomme einen Compilerfehler. Ich verstehe, warum ich einen Kompilierungsfehler in der oben genannten Methode der Deklaration für Array von bekomme int Datentyp, da var [i] keine Referenz auf eine Variable ist, auf die ein Zeiger zeigen muss, d. h. seine Adresse, aber sollte nicht auch ich Fehler durch die gleiche Logik in der Deklaration von meinem erhalten char Zeigerfeld.

Was ist der Grund, dass es in akzeptabel ist? char Array von Zeigern?

Ist " ein Zeichenfolgenwert  "eine Adresse von etwas, auf das ein Zeiger zeigen kann oder ist es nur ein const Zeichenfolgenwert.


5
2017-07-06 11:43


Ursprung


Antworten:


char *names[] = {"Mathew Emerson", "Bob Jackson"};

Ist in C ++ nicht legal. Ein String-Literal hat den Typ const char[] so ist es illegal, es als a zu speichern char* wie es gegen const-Korrektheit verstößt. Einige Compiler erlauben es, dies immer noch als ein Vermächtnis von C zu kompilieren, da String-Literale den Typ haben char[] aber es ist kein Standard C ++. Wenn Sie die Warnungen auf Ihrem Compiler auftauchen, sollten Sie etwas in der Art von

main.cpp: In function 'int main()':
main.cpp:5:53: warning: ISO C++ forbids converting a string constant to 'char*' [-Wpedantic]
     char *names[] = {"Mathew Emerson", "Bob Jackson"};

Wenn Sie ein Array von Strings wollen, dann schlage ich vor, dass Sie ein verwenden std::string mögen

std::string names[] = {"Mathew Emerson", "Bob Jackson"};

Der Grund

char *names[] = {"Mathew Emerson", "Bob Jackson"};

"funktioniert" ist, dass die String-Literale Arrays implizit zu Zeigern zerfallen

{"Mathew Emerson", "Bob Jackson"}

Wird

{ address_of_first_string_literal, address_of_second_string_literal}

und dann werden diese verwendet, um die Zeiger in dem Array zu initialisieren.

int *ptr[] = {var[0], var[1], var[2], var[3]};

Kann nicht funktionieren, weil var[N] ist ein Verweis auf die int im Array und nicht ein Zeiger.


7
2017-07-06 11:49



"Mathew Emerson" ist vom Typ const char* - Es ist bereits ein Zeiger, so dass Sie es direkt in einem Array von Zeigern speichern können. Der Grund, den du brauchst & für den Int-Fall ist "umwandeln" int zu int*.


1
2017-07-06 11:48



(Ignoriere das Const-Problem wie in anderen Antworten erwähnt ...)

Jedes Stringliteral, das Sie schreiben ("Mathew Emerson", "Bob Jackson", ...) benötigt später einen Speicherort im kompilierten Code.

Es ist, als hättest du irgendwo geschrieben

char const[] MathewEmerson = { 'M', 'a', /*...*/, 'o', 'n', 0 };

So können Sie Ihr char const * Array dann als:

char const* names[] = { &MathewEmerson[0], /*...*/ };

Wie bei Arrays ist die Adresse des Arrays selbst und des ersten Elements identisch, und Arrays werden implizit in Zeiger umgewandelt, die Sie stattdessen schreiben können

char const* names[] = { MathewEmerson, /*...*/ };

All dies geschieht implizit für Sie, wenn Sie String-Literale verwenden.

Ähnlich hätten Sie schreiben können:

int *ptr[] = {var, &var[1], &var[2], &var[3]};

(Hinweis: varnicht &var[0] für den ersten Punkt) und wenn wir weiter gehen, sogar:

int *ptr[] = {var, var + 1, var + 2, var + 3};

Das Ergebnis wäre immer das Gleiche gewesen. Lesbarkeit, Verständlichkeit einer Variante gegenüber einer anderen? Nun, ein anderes Thema ...


1
2017-07-06 11:59



Dein Missverständnis ist in deiner Interpretation dessen eingeschlossen, was repräsentiert wird durch: "Mathew Emerson"

Dies ist ein Array von Zeichen, die im Nur-Lese-Speicher als Teil des Bootstrappings Ihres Programms instanziiert werden. Dieses Array von Zeichen heißt a Zeichenfolge Literal, insbesondere a:

Narrow Multibyte String Literal. Der Typ eines Zeichenfolgezeichens ohne Präfix ist const char[]

NathanOliver's Antwort korrekt beschreibt, dass der Compiler die Warnstufe nicht hoch genug eingestellt hat, const char[] in einen zerfallen char*. Das ist sehr schlecht, weil:

Der Versuch, ein Zeichenfolgenliteral zu ändern, führt zu undefiniertem Verhalten: Sie können in einem schreibgeschützten Speicher (z. B. .rodata) gespeichert oder mit anderen Zeichenfolgenliteralen kombiniert werden[1]

Es wäre jedoch vollkommen legal und logisch gewesen, dies zu tun: const char *names[] = {"Mathew Emerson", "Bob Jackson"} Hoffentlich klärt das für Sie, was gerade passiert, dass Sie mit einem String-Literal arbeiten ist Arbeiten mit einem Zeiger. Dein Code: int *ptr[] = {var[0], var[1], var[2], var[3]} ist dann illegal, weil var[0] ist ein int& nicht ein int*. Es wäre ebenso illegal zu tun: char* ptr = {names[0][0], names[0][1], names[0][2], names[0][3]} Wiederum wäre das Problem, dass ich damit arbeiten würde char&S nicht char*s.


1
2017-07-06 13:03