und ich rufe getString() von main() auf diese Weise auf:
const char * s = getString();
1) Laut gdb die Variable ptr wird auf dem Stack gespeichert, aber die Zeichenfolge, auf die ptr zeigt ist nicht:
(gdb) p &ptr
$1 = (const char **) 0x7fffffffe688
(gdb) p ptr
$2 = 0x4009fc "blah blah"
Bedeutet dies, dass “blah blah” keine lokale Variable in getString() ist?
Ich denke, wenn es eine lokale Variable wäre, könnte ich sie nicht an meine main () -Funktion übergeben … Aber wenn nicht, wo wird sie gespeichert? Auf dem Haufen? Ist das eine “Art” dynamische Speicherzuweisung, die vom Betriebssystem jedes Mal implementiert wird, wenn es auf eine Zeichenfolge trifft, oder was?
2) Wenn ich ein Array anstelle eines Zeigers verwende, so:
(und natürlich wird das Programm kompiliert, aber es funktioniert nicht).
Eigentlich, wenn ich gdb frage, bekomme ich
(gdb) p &a
$2 = (const char (*)[15]) 0x7fffffffe690
Aber das dachte ich const char * ptr und konstantes Zeichen a[] waren im Grunde dasselbe. Sieht so aus, als wären sie es nicht.
Liege ich falsch? Was genau ist der Unterschied zwischen den beiden Versionen?
Vielen Dank!
stackoverflow.com/questions/3862842/…
– Matte
22. Dezember 2012 um 16:08 Uhr
Gut formulierte Frage, auch wenn es sich um eine Wiederholung handelt.
– Mats Petersson
22. Dezember 2012 um 16:11 Uhr
Wenn du schreibst
const char *ptr = "blah blah";
dann passiert folgendes: der Compiler generiert einen konstanten String (vom Typ char []) mit Inhalt "blah blah" und speichert es irgendwo im Datensegment der ausführbaren Datei (es hat im Grunde eine ähnliche Speicherdauer wie die von Variablen, die mit der deklariert wurden static Stichwort).
Dann die Adresse dieser Zeichenfolge, die lautet gültig während der gesamten Laufzeit des Programms, gespeichert ist in der ptr Zeiger, der dann zurückgegeben wird. Alles ist gut.
Bedeutet dies das "blah blah" ist keine lokale Variable in getString()?
Lassen Sie mich mit einem gebrochenen englischen Satz antworten: ja, das ist es nicht.
Wenn Sie jedoch ein Array deklarieren, wie in
const char a[] = "blah blah";
dann generiert der Compiler keinen statischen String. (Tatsächlich ist dies ein etwas spezieller Fall beim Initialisieren von Strings.) Es generiert dann Code, der ein ausreichend großes Stack-Speicherstück für die zuweist aReihe (es ist kein Zeiger!) und füllt es mit den Bytes des Strings. Hier aist eigentlich eine lokale Variable und die Rückgabe seiner Adresse führt zu undefiniertem Verhalten.
So…
Aber das dachte ich const char *ptr und const char a[] waren im Grunde dasselbe.
Zeichenfolgenliterale haben einen Typ char []Sie sind nicht const-qualifiziert, obwohl es schön wäre.
– effe
22. Dezember 2012 um 16:16 Uhr
@effeffe Du bist die zweite Person, die das sagt. Es muss wahr sein. (Was für eine hirnlose Widersprüchlichkeit!)
– Benutzer529758
22. Dezember 2012 um 16:20 Uhr
Es ist wahr. Es ist ein Überbleibsel der frühen Tage, als es keine gab const. Vor der Einführung von constdie einzigen Zeichenfolgenliterale vom Typ könnte haben war char[N] (für angemessen N). Eine spätere Änderung wäre wahrscheinlich als zu bahnbrechende Änderung angesehen worden.
– Daniel Fischer
22. Dezember 2012 um 16:24 Uhr
Bah, was für ein dummer Tippfehler, danke für die Korrektur @DanielFischer. (Ja, ich verstehe die Argumentation, aber wir hatten zwei große Überarbeitungen des Standards seit K&r, C89 und C99, ich verstehe nicht, warum diese Änderung nicht vorgenommen werden konnte.)
– Benutzer529758
22. Dezember 2012 um 16:25 Uhr
Zitieren der C99-Begründung: “String-Literale haben jedoch nicht den Typ Array von const char, um die Probleme der Zeigertypprüfung zu vermeiden, insbesondere bei Bibliotheksfunktionen, da die Zuweisung eines Zeigers auf const char zu einem einfachen Zeiger auf char nicht zulässig ist.”
– effe
22. Dezember 2012 um 16:26 Uhr
md5
Ich denke, wenn es eine lokale Variable wäre, könnte ich sie nicht an meine main () -Funktion übergeben … Aber wenn nicht, wo wird sie gespeichert?
Zeichenfolgenliterale werden normalerweise in einem schreibgeschützten Datenabschnitt gespeichert (.rodata). C-Standard sagt nur, dass sie eine statische Speicherdauer haben. Daher können Sie einen Zeiger auf ein solches Literal zurückgeben, dies ist jedoch bei Arrays nicht der Fall.
Im folgenden Beispiel zeigt das Objekt von p1 hat eine statische Speicherdauer, während das Array p2 hat eine automatische Speicherdauer.
Beide p1 und p2 hat eine automatische Speicherdauer, während das Objekt durch zeigt p1 hat eine statische Speicherdauer. (und vielleicht sollte die Funktion nicht sein void :P)
– effe
22. Dezember 2012 um 16:30 Uhr
Sie haben recht damit, dass sie nicht dasselbe sind. Zeichen a[] ist ein Array, das auf dem Stack gebildet und dann mit “blah..” gefüllt wird – innerhalb der Funktion haben Sie im Wesentlichen `const char a[15]; strcpy(a, “bla bla bla”);”
The const char *ptr = "blah blah blah"; Andererseits ist es einfach ein Zeiger (der Zeiger selbst befindet sich auf dem Stapel), und der Zeiger zeigt auf die Zeichenfolge “blah blah blah”, die woanders gespeichert ist [in “read only data” most likely].
Sie werden einen großen Unterschied feststellen, wenn Sie versuchen, etwas zu ändern, z. a[2] = 'e'; vs ptr[2] = 'e'; – Der erste wird erfolgreich sein, weil Sie einen Stapelwert ändern, während der zweite (wahrscheinlich) fehlschlägt, weil Sie einen schreibgeschützten Speicher ändern, der natürlich nicht funktionieren sollte.
Grijesh Chauhan
In Ihrer Funktion ist der Umfang von a[] array ist innerhalb der Funktion getString2(). es ist lokale Array-Variable.
Im obigen Fall Zeichenfolge "blah blah blah" Kopien Faust hinein a[] und Sie versuchen, dieses Array mit zurückzugeben return a Anweisung, aber keine konstante Zeichenfolge.
Wo wie im ersten Code getString() : ptr = "blah blah"; ptr zeigt auf Speicher mit globalem Geltungsbereich.
Der erste ist ein Zeiger auf ein Zeichenfolgenliteral. Der Zeiger selbst befindet sich im automatischen Speicher. Die Zeichenfolge befindet sich im statischen Nur-Lese-Speicher. Es ist unveränderlich.
Der zweite ist ein automatischer (Stapel) char array (und diese Rückgabe ist, wie die Warnung sagt, nicht zulässig).
14324500cookie-checkWie werden C-Strings im Speicher zugewiesen?yes
stackoverflow.com/questions/3862842/…
– Matte
22. Dezember 2012 um 16:08 Uhr
Gut formulierte Frage, auch wenn es sich um eine Wiederholung handelt.
– Mats Petersson
22. Dezember 2012 um 16:11 Uhr