wieder mal ein paar char Probleme...
-
Hallo, ich habe mal wieder ein Problem (mal was ganz neues) und zwar will ich endlich genau dahinterkommen, was es alles mit den chars auf sich hat.
char * makiert ja einen pointer, warum aber kann ich zum Beispiel so machen:
char *testVar; testVar = "blabla"; cout << "diese var gibts doch" << testVar << "\n\n";
Wenn das stimmen sollte, was in meinem c++ Buch steht dürfte das so gar nicht funktionieren, weil ich dem Pointer ja noch keinen Ziel char zugewiesen habe.
Aber ich denke da habe ich vielleicht einfach nur etwas falsch verstanden.Das schlimme ist: ich habe mein missverständnis die ganze Zeit ignoriert und einfach fröhlich mal char und mal char* verwendet.
Jetzt kommen aber langsam meine Probleme, und zwar immer wenn es darum geht aus meinem char* eine normale char- variable (array) zu machen.Da kommt vom Kompiler der lustige Hinweis, dass das nicht geht :).
Kann mich vielleicht mal einer aufklären, was genau es jetzt mit diesem char zeugs auf sich hat ?
Danke im vorraus
-
http://www.c-plusplus.net/forum/viewtopic.php?t=39462
char *testVar = "blabla";
so wie ich das versteh sind char pointer einfach ne ausnahme, sodass man ihnen strings zuweisen kann
in dem obigen fall enthält testVar einfach nur die adresse des ersten zeichens im speicher
hinter dem letzten zeichen steht eine binären null '\0' damit dein programm weiss wo der string aufhörtzum verständnis
testVar; //=="blabla" == char*
*testVar; //== 'b' == chartestVar + 1; //=="labla" == char*
*(testVar + 1); //=='l' == charwenn du einen char* in einen char array kopieren willst (oder ähnliche operationen) musst du die ansi funktionen verwenden
-
naja du hast recht, auf den ersten Blick ist es ein Pointer, was es natürlich auch immer bleiben wird. Die Lösung des Problems ist folgendes:
Ein Pointer ist ja einfach nur eine Speicheraddresse. Und zwar handelt es sich bei einem Pointer um die Addresse im Speicher, bei der das erste Byte der Variablen liegt, auf die der Pointer zeigt.
Hast du also einen char* der 5 char elemente reserviert, dann zeigt dieser zeiger auf den ersten char. Das du an alle anderen Elemente rankommst, liegt daran, dass du im gegensatz zu einer Referenz den Zeiger neu initialisieren kannst, also du kannst ihn auf die anderen Elemente setzen. Das machst du normalerweise, indem zu wie auf einen Array auf die Elemente zugreifst. Im Speicher passiert dann in etwa sowas:
char* ptr = new char [10]; strcpy ((char*), ptr, (char*)"hello world"); //zugriff auf das erste element direkt über den zeiger char test = ptr[0]; //über den Array char test = *ptr; //über den Zeiger, weil ptr auf die daten an ptr[0] zeigt //zugriff auf das n-te Element int n = 4; char test = ptr[n]; // Zugriff über Array char test = *(ptr + n * sizeof (char)); //Zugriff über Zeiger über Verschiebung
Wenn Du jetzt sowas machst:
char* ptr = "hello world";
dann wird intern speicher schon reserviert. In dem Fall 5 (für das hello) 6 (für das " welt") und 1 für das \n macht 12 Character. Wenn du jetzt versuchst noch was in die Zeichenkette zu schreiben, wird dies fehlschlagen. Kannst es ja mal versuchen.
Ich hoffe der kleine Exkurs hat geholfen.
Gruß Sebastian
-
ja sogar sehr, danke euch beiden, so etwas steht leider nie in irgendeinem Buch...
-
Hi,
valide:
const char* a = "Hallo";
invalide:
char* a; a = "Hallo";
Ich könnte mir vorstellen, dass der Compiler das so optimiert, dass da char* a = "Hallo" steht und das daher funktioniert, aber eigentlich ist sowas nicht möglich.
MfG Eisflamme
-
Mis2com schrieb:
invalide:
char* a; a = "Hallo";
Falsch. Schlechter Stil, aber nicht "invalide".
Ich könnte mir vorstellen, dass der Compiler das so optimiert, dass da char* a = "Hallo" steht und das daher funktioniert, aber eigentlich ist sowas nicht möglich.
-
Hi,
nö? wieso geht das?
wie lange lebt "hallo" denn?MfG Eisflamme
-
"hallo" ist ein Stringliteral und lebt somit über die gesamte Dauer der Programmausführung.
-
Hi,
wo lebt so ein Literal denn, dass es so lange lebt? Und wieso ist das dann schlechter Stil?
fg Eis
-
Seltsame Fragen stellst du, wo du doch gerade noch als valide bezeichnet hattest, einen const char* auf ein Stringliteral zu setzen.
Was meinst du damit, wo es lebt? Dazu macht der Standard keine Aussage. Ich würde sie im Datensegment ablegen, ungefähr dort, wo auch die globalen und statischen Variablen liegen. Der gcc legt Stringliterale in einem Read-Only-Speicherbereich ab.
Was auch gleich beantwortet, warum es schlechter Stil ist, einen char* auf ein Literal zeigen zu lassen. Das Verändern das Literals führt zu undefiniertem Verhalten, also sollte man davon absehen, und nur const char* darauf zeigen lassen, damit der Compiler sowas gleich abfängt. Aus Kompatibilitätsgründen zu C gibt es aber eine automatische const char* zu char* Umwandlung in C++, die m.W. allerdings auf Literale beschränkt ist.
-
Hi,
ok, danke, jetzt ist mir das klar.
Wegen const char* chfff = hatte ich gehört, dass manche Compiler das wohl auch so optimieren würden, dass für chfff dann auch gleich Speicher belegt wird und das reinKOPIERT wird, also so als Feature, aber k.A.MfG Eisflamme
-
Mis2com schrieb:
Wegen const char* chfff = hatte ich gehört, dass manche Compiler das wohl auch so optimieren würden, dass für chfff dann auch gleich Speicher belegt wird und das reinKOPIERT wird, also so als Feature, aber k.A.
Klingt eher nach einer Pessimierung
Was soll das bringen? Die Allokation dauert doch nur, und wer gibt das dann frei? Verwechselst du das vielleicht hiermit:const char foo[6] = "hallo";
-
Bashar schrieb:
Seltsame Fragen stellst du, wo du doch gerade noch als valide bezeichnet hattest, einen const char* auf ein Stringliteral zu setzen.
Was meinst du damit, wo es lebt? Dazu macht der Standard keine Aussage. Ich würde sie im Datensegment ablegen, ungefähr dort, wo auch die globalen und statischen Variablen liegen. Der gcc legt Stringliterale in einem Read-Only-Speicherbereich ab.
Japp. Dort wird jedes Literal maximal einmal in einer Tabelle abgelegt. Kann man auch leicht prüfen:
#include <iostream> using namespace std; int main() { const char * c1, *c2, *c3; c1 = "hallo"; c2 = "hallo"; c3 = "Hallo"; cout << (c1==c2) << endl; // 1 cout << (c1==c3); // 0 cin.get(); return 0; }
-
Hi,
Bashar:
Genau.MfG Eis