frage zu strings bzw char *
-
ich habe kürzlich in einem programm folgende zuweisung verwendet
char *MeinString; /* je nachdem entweder */ MeinString = "Informationstext 1\0"; /* oder */ MeinString = "Informationstext alternative...\0";
die ausgaben haben alle super funktioniert, jedoch verstehe ich nicht ganz, wie hier bei der speicherreservierung vorgegangen wird. "kümmert" sich c hier darum, dass immer genug speicher für MeinString zur verfügung steht und schützt diesen, egal wie lang MeinString wird? oder hatte ich nur glück, dass das geklappt hat? ich wusste nicht wirklich, was ich da tat, war nur froh dass es hingehauen hat
kann ich diese vorgehensweise weiterhin gefahrenlos verwenden?mfg, jule
-
jule37 schrieb:
jedoch verstehe ich nicht ganz, wie hier bei der speicherreservierung vorgegangen wird.
Ist prinzipiell undefiniert, wie weit soll sich eine Erklärung denn auf eine Plattform beschränken?
"Normalerweise" (sprich: bei dir) geht das ungefähr so, daß der String bereits vollständig in der ausführbaren Datei liegt und durch die Zuweisung der Zeiger nur passend umgebogen wird. Es wird also durch die Zuweisung selbst kein Speicher reserviert, weil das bereits beim Starten des Programmes geschehen ist.jule37 schrieb:
"kümmert" sich c hier darum, dass immer genug speicher für MeinString zur verfügung steht und schützt diesen, egal wie lang MeinString wird?
Ja.
jule37 schrieb:
oder hatte ich nur glück, dass das geklappt hat?
Nein.
jule37 schrieb:
kann ich diese vorgehensweise weiterhin gefahrenlos verwenden?
Ja. Aber lass den Nullterminator ("\0") da weg, der wird ebenfalls durch den Compiler automagisch angehängt.
-
danke für deine antwort
tommie-lie schrieb:
... Es wird also durch die Zuweisung selbst kein Speicher reserviert, weil das bereits beim Starten des Programmes geschehen ist.
heisst das, dass alle varianten des strings irgendwo den speicher "vollstopfen", selbst wenn vielleicht nur eine zur laufzeit je verwendet wird?
gibt es dann vielleicht auch eine elegantere methode mit strings umzugehen? also dass immer nur der speicher, der gerade tatsächlich benötigt ist angefordert wird. oder ist es müßig sich darüber sosehr den kopf zu zerbrechen?
-
Die einzige Möglichkeit, dass konstante Strings nicht irgendwo im Programmcode rumliegen, ist es sie in eine Datei (bzw. sonstige externe Stelle) auszulagern. Hat aber wenig Sinn, wenn es nicht sehr viele sind.
MfG SideWinder
-
Eine weitere Möglichkeit unter Windows wäre eine STRINGTABLE-Ressource. Dies sei jedoch nur der Vollständigkeithalber erwähnt.
Greetz, Swordfish
-
[quote="jule37"]
char *MeinString; /* je nachdem entweder */ MeinString = "Informationstext 1\0"; /* oder */ MeinString = "Informationstext alternative...\0";
Hi jule,
das dies funktioniert lieget daran das "Informationstext 1\0" und "Informationstext alternative...\0" Literale sind und beim Start des Programms automatisch Speicher dafür allokiert wird. Wenn du unter Linux arbeitest und einen strings auf das übersetzte Programm machst, dann wirst du die Texte auch wieder finden.Mit MeinString zeigst du nur auf die zuvor beim start allokierten speicherberreiche bzw. biegst den Zeiger eben auf einen anderne um.
Natürlich kannst du es weiterverwenden, solange du du den vordefinierten Text (im Quellcode) nicht im selben Speicherbereich ändern willst.
greetz
codefrag
-
jule37 schrieb:
heisst das, dass alle varianten des strings irgendwo den speicher "vollstopfen", selbst wenn vielleicht nur eine zur laufzeit je verwendet wird?
"Vollstopfen" ist bei den Größenordnungen lustig. Wieviele Stringliterale hast du im Quellcode? Ein Kilobyte? Und wie groß ist der Rest des Programmes im Vergleich dazu? Siehste?
Nur den Speicher für tatsächlich benutzte Strings zu allokieren wird nicht klappen. Die Strings müssen irgendwo gespeichert werden, falls sie doch verwendet werden. Da ist es doch schon elegant, daß nicht bei der Zuweisung nochmals Speicher auf dem Heap (über malloc()) allokiert wird und der String aus der Ausführbaren Datei dorthin kopiert wird, sondern der schon vorhandene Speicherbereich benutzt wird. Woher soll denn der Compiler zur Kompilierungszeit wissen, welche Strings beim Aufruf des Programmes benötigt werden.
Stell dir vor, du hast ein Programm, daß einen Kommandozeilenparameter annimmt und je nach Wert dieses Parameters unterschiedliche Strings ausgibt. Der Compiler kann nicht wissen, mit welchem Parameter du später das Programm aufrufen wirst, also muss er alle Strings mit in das Programm packen.
Jeder String, den du im Quellcode verwendest (unabhängig davon, ob er später zur Laufzeit verwendet wird), landet auch im Programm und wird später beim Ausführen in den Speicher geladen. Das liegt in der Natur moderner Systeme, die nicht während der Ausführung Befehl für Befehl in den Speicher laden, sondern das Programm einmal vollständig in den Speicher laden.jule37 schrieb:
oder ist es müßig sich darüber sosehr den kopf zu zerbrechen?
Ja, ist es. Wenn dein Programm optimieren willst, tue das an anderen Stellen.
Swordfish schrieb:
Eine weitere Möglichkeit unter Windows wäre eine STRINGTABLE-Ressource. Dies sei jedoch nur der Vollständigkeithalber erwähnt.
Ressourcen sind unter Windows Teil des Images und werden somit auch zusammen mit dem Programm in den Speicher geladen. Der Vorteil von Stringressourcen ist die einfache Veränderbarkeit ohne Neukompilation. Aber die erkauft man sich damit, daß man für jede Stringzuweisung Funktionen aufrufen muss, die den String aus der Ressource laden. Und selbst wenn man die Ressource in eine Ressourcen-DLL steckt und die erst bei Bedarf lädt, werden beim Bedarf alle Strings auf einmal in den Speicher geladen, womit man wieder am Anfang steht.
-
Sind eher zur Internationalisierung, etc. gedacht. Da kann man dann sehr schnell ein ResourceBundle "en" durch eins mit dem Namen "de" austauschen
MfG SideWinder
-
Hallo ich hätte hier auch eine Frage zur Speicherverwaltung
const char* createStringPointer() { char* mystring = "This is my string"; return mystring; } int main() { const char* r_string = createStringPointer(); printf("%s\n",r_string); exit(0); }
Ich verstehe nicht genau warum das was ich da geschrieben habe überhaupt
funktioniert! Wird hier Speicher auf dem Heap reserviert obwohl ich kein malloc
gemacht habe? Warum funktionert der printf überhaupt? Wo geht mystring out of scope?
Evt überhaupt nicht?
-
xauser schrieb:
Ich verstehe nicht genau warum das was ich da geschrieben habe überhaupt
funktioniert! Wird hier Speicher auf dem Heap reserviert obwohl ich kein malloc
gemacht habe? Warum funktionert der printf überhaupt? Wo geht mystring out of scope?
Evt überhaupt nicht?Ja da du ein Stringliteral benutzt, für das zum Programmstart automatisch Speicher allokiert wird.
Genauer wie es funktioniert ist hier:
http://home.fhtw-berlin.de/~junghans/cref/CONCEPT/string.htmlgreetz
der codefrag
-
Nein, in deinem Beispiel wird kein Speicher auf dem Heap reserviert. Der Compiler legt den Zeichenkettenliteral "This is my string" in deiner .exe ab. Mit
char* mystring = "This is my string";
lädst du lediglich die Adresse der Zeichenkette in mystring und in weiterer Folge mit
const char* r_string = createStringPointer();
nach r_string. printf( ) gibt diesen dann aus.
BTW: Der Aufruf von exit( ) am ende von main( ) ist für die Katz.
Greetz, Swordfish
-
- Es wird kein Speicher auf dem Heap reserviert
- Die Zeichenfolge "This is my string" existiert bereits im .exe-File
- Der Scope von mystring selbst (4 Bytes) endet nach Beendigung der Funktion
- Es wird nur die Adresse des existierenden "This is my string" zurügereichtDe Facto (nach Compiler-Optimierung) ist die Funktion äquivalent zu
const char* createStringPointer() {return "This is my String";}
BTW: Es ist ein char-Pointer, kein Stringpointer.
Ein String ist bereits ein char-Pointer.