2017-04-05 2 views
1

Wir haben es mit einem konstanten Zeiger zu tun, , so dass die Adresse, die er enthält, nicht geändert werden kann. Aber der Inhalt dieser referenzierten Speicheradresse soll veränderbar sein ...So ändern Sie den Inhalt von char * const, nachdem er gesetzt wurde (C)

Immer noch bekomme ich Kompilierung/Segmentierung Fehler Fehler, wenn Sie dies versuchen.

#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
    char * const c_ptr = "firstValue"; // now c_ptr is a const ptr to an immutable string literal, 
            //we can't change it unless we declare char [] instead 
    printf("%s",c_ptr); 

    *c_ptr="hsdsdsd"; // better to use strcpy(c_ptr, "hsdsdsd"); 

    printf("%s",c_ptr); 
    return 0; 
} 

main.c: In Funktion 'main':
main.c: 8: 8: Warnung: Zuordnung ohne eine ganze Zahl von Guss Zeiger macht [standardmäßig aktiviert]
* c_ptr =“ hsdsdsd ";

Segmentation fault (core dumped)

+3

Lesen Sie ein grundlegendes C-Buch, bitte. '* c_ptr'! =' c_ptr', um mit zu beginnen. –

+0

Lesen Sie die Warnung. Es wirft Pointer-> Int-> Char. –

+0

Warum sollte ich ändern, wohin es zeigt? es ist ein konstanter Zeiger ... –

Antwort

2

Nun, die Daten, die der Zeiger zeigt auf einen konstanten Zeiger ändern kann, aber nicht, wenn Sie es initialisieren ein Zeichenfolgenliteral verwenden. Sie haben die eher seltsame Eigenschaft, den Typ char * zu haben, aber nicht in der Lage zu ändern.

So können Sie tun:

char data[10] = "foobar"; 
char * const ptr = data; 

printf("%s\n", ptr); // prints foobar 
*ptr = 'z'; 
printf("%s\n", ptr); // prints zoobar 
+0

Wird der Standard nicht so geändert, dass String-Literale nur aus Legacy-Code-Gründen vom Typ const char * sind? –

+0

@AjayBrahmakshatriya Nein, ich denke nicht. – unwind

+0

@AjayBrahmakshatriya Meistens wird es nicht geändert, weil das C-Komitee schmerzlich konservativ ist und es hassen würde, die Sprache zu verbessern. C++ hat es vor langer Zeit geändert und es hat auch für Legacy-Code keine größeren Probleme verursacht. Das liegt daran, dass alter fauler Legacy-Code mit alten faulen Legacy-Compilern kompiliert wird und nicht mit dem neuesten und größten standardkonformen Compiler. Daher haben Änderungen in einem Standard nicht so viel Einfluss auf alten Code, wie sie befürchten. – Lundin

1

Zuerst werden C-Strings null beendet char-Arrays, und Sie können nicht zuordnen Arrays, müssen Sie es jedes Element ändern.

Auch im Allgemeinen setzen die Compiler String-Literale wie "firstValue" in einen schreibgeschützten Speicherbereich, so dass Sie nicht ändern können, müssen Sie ein Char-Array verwenden, um die Zeichenfolge zu initialisieren.

char s[] = "firstValue"; 
const char*const ptr = s; 
ptr[0] = 'z'; // change contents pointed by ptr, or: 
strncpy(ptr, "abc", 3); 
+0

Ist der schreibgeschützte Speicherbereich Teil des Stacks ?. Wenn wir den Bereich verlassen, in dem das unveränderliche Zeichenfolgenliteral deklariert wurde, wird der belegte Speicher wieder wiederverwendbar (statisch zuweisbar)? , oder alle schreibgeschützten Daten werden nur zur Kompilierungszeit/Ausführungsbeginn gesetzt. –

+1

@IdanBanani Es gibt kein Konzept von "stack", das von C benötigt wird. Und String-Literale haben "statischen" Speicher, sie gehen nicht aus dem Geltungsbereich. – unwind

+1

@IdanBanani Es ist kein Teil des Stapels. Wenn die Funktion zurückkehrt, wird sie nicht ausgeblendet, aber der Zeiger selbst ist auf dem Stapel und wird ausgeblendet. – fluter

1

char * const c_ptr bedeutet einen nicht konstanten Zeiger auf const Daten. Das bedeutet, dass Sie die Zeigervariable selbst schreibgeschützt gemacht haben, aber nicht die Daten, auf die verwiesen wird.

Wenn Sie *c_ptr = 'a' tun, dann würde der Compiler es nicht verhindern, weil Sie ihm gesagt haben, dass die angegebenen Daten lesen/schreiben sind. Das ist in diesem Fall nicht wahr, es ist ein String-Literal und das Schreiben wird dazu führen, undefined Verhalten, weshalb Sie einen Absturz bekommen.

C11 6.4.5/7

Wenn das Programm ein solches Array zu ändern versucht, ist das Verhalten undefiniert.

Korrigieren Sie den Code, indem Sie die Deklaration in const char* c_ptr ändern.
Oder alternativ const char* const c_ptr.

Nun, wie sich herausstellt, diese ist unveränderlich, denn wenn man jetzt strcpy(c_ptr, "str") versuchen würde, würden Sie einen ungültigen Zeigerumwandlungs erhalten, da die Funktion eine char* erwartet.


*c_ptr="hsdsdsd"; ist Unsinn und wird auf einem konformen C-Compiler nicht kompiliert werden, da Sie versuchen, eine Adresse zu einer einzelnen char Variablen zugewiesen werden, was nicht erlaubt ist. (Eine Constraint-Verletzung der einfachen Zuordnungsregeln).

Verwandte Themen