Algemeines zu char * und char[]

Ach so, das wäre natürlich schön, denn wieviel Platz hinterher beansprucht wird, ist mir erstmal egal, hauptsache, die exe bleibt so klein wie möglich!

Jetzt habt iht mich auf noch eine Frage gebracht:
Besser wäre:

Code:
--------------------------------------------------------------------------------

char x[] = "test";
//oder:
char* g = new char[256];
strcpy(g,"test");



--------------------------------------------------------------------------------

Hier zeigt ja g dann auf ein array!
und ich kann dafür strcpy benutzen, was ich für einen sonstigen char-Zeiger nicht verwenden kann!

kann ich denn für g jetzt auch Fnktionen verwenden, die ich sonst nur für char-Zeiger verwenden kann?

z.B habe ich oft Probleme, wenn ich einem char-Array eine char-Zeiger-Variable zuordne:
Code:
char t[255];
char *s="test";
t=s;

Ich kann nur entweder mit strcpy ein char-Array in eina nderes kopieren, oder mit strdup eine char-Zeiger-Variable in eine andere kopieren!

Wenn ich jetzt wie oben
Code:
char * g=new char[255];

verwende, dann könnte ich die Variable wie eine Zeigervaribale verwenden, müßte aber nicht Angst haben, daß ich eine Speicherverletzung provoziere (vorausgesetzt die Variable wird nicht länger als 255)!

Also meine Frage, wie ist diese Variable dann zu behandeln, wie ein Array oder wie ein Zeiger?
 
Ich glaube, du hast noch nicht so genau verstanden, was ein Zeiger und was ein Array ist.

Zeiger: ist 4 Byte gross und beeinhaltet eine Addresse deines Arbeitsspeichers. (muss zwar nicht unbedingt wirklich im Arbeitsspeicher sein, aber für dich macht es keinen Unterschied).
Er zeigt also auf einen Buffer/Speicherbereich.
Der Typ char* gibt nur an, dass das, was an diesem Speicherbereich liegt, als char zu behandeln ist.

char* x = new char[256];
reserviert einen Speicherbereich von sizeof(char)*256 Byte und liefert dessen Speicheraddresse zurück, die anschliessend der Variable zugewiesen wird.
da aber x nicht konstant ist (das wäre char*const x), kann es auch im späteren Programmverlauf auf andere Stellen des Speichers verweisen.

Ein Array dagegen ist selbst ein Speicherbereich.
char f[256]; hat die Grösse sizeof(char)*256 Byte und nicht 4 Byte, wie ein Zeiger es immer hat.
Nur der Name "f" kann im Übrigen wie ein konstanter Zeiger verwendet werden, der auf eben den Speicherbereich zeigt, in dem dieses Array liegt, daher kann nicht f selbst neu zugewiesen werden, sondern nur das verändert, worauf es zeigt.

Also -> Arrays können nur bei Initialisierung String zugeordnet bekommen (die werden dann einfach reinkopiert). Nach der Initialisierung kann man sie nur noch per strcpy usw beschreiben.

Wenn du was nicht verstanden hast (ich glaub, ich kann nicht gut erklärn), schau lieber nochmal in einem C++-Tutorial nach. Zb auf http://www.c-plusplus.de/index.php
 
Danke für den kleinen Kurs, habs glaub ich verstanden, nur noch eine Frage!

char* x = new char[256];
reserviert einen Speicherbereich von sizeof(char)*256 Byte und liefert dessen Speicheraddresse zurück, die anschliessend der Variable zugewiesen wird.
da aber x nicht konstant ist (das wäre char*const x), kann es auch im späteren Programmverlauf auf andere Stellen des Speichers verweisen.

Wieso macht man das dann, wenn x hinterher auf einen anderen Speicher zeigen kann?
Und in welchem FAll zeigt x auf einen anderen Speicherbereich?

wenn ich jetzt immer x einen String zuweise: x="string"; dann müßte string immer in dem reservierten Speciherbereich stehen, da x die Adresse beinhaltet!

Wenn ich jetzt x eine andere char-zeiger variable zuordne, dann zeigt x auf den Speicherbereich der andren Variablen, richtig?
 
Stell dir die Arbeitsweise deines Prozesses mal etwas technischer an:
Jedes Byte in deinem Speicher ist addressierbar.
Speicherplatz 1 ist das 1. Byte, 2 das 2. usw.

Nehmen wir mal an, deine Exe ist 1kb gross und wird gleich in die ersten 1000 Bytes Speicher geschrieben.

Bis sagen wir zu Byte 400 stehen irgendwelche Header.
Dann folgen globale Variablen, Strings, alles einfach direkt hintereinander.
der String "hallo" ist zB an Byte 450 angelegt, und reicht, da er nicht Unicode ist, bis einschlieslich Byte 455 (5Zeichen + '\0')

Nehmen wir an, du hast einen globalen Zeiger char*x deklariert. Er belegt nun die Bytes 500 bis 503, da er 4 Byte gross ist.
Dann ist erstmal undefiniert, an welche Stelle er zeigt, da du ihn nicht initialisiert hast, is ja logisch. Der Versuch ihn zu dereferenziern würde sehr wahrscheinlich zum Programmabsturz wegen nicht authorisiertem Speicherzugriff führen.
machst du jetzt x="hallo", werden diese 4 Bytes einfach mit der Addresse 450 beschrieben, da dort der String "hallo" liegt. Schreibst du im späteren Programmverlauf noch irgendwo x="anderer string"; nehmen die 4Bytes die Addresse des ersten Bytes von "anderer string" ein, dabei geschieht aber nichts mit dem Speicher an Byte 450.
Das ist ja der Sinn von Zeigern -> Sie verweisen auf andere Variablen, so können zur Laufzeit Variablen verwendet werden, die zur Kompilationszeit noch nicht mal bekannt sein müssen.

Ich glaube, eins deiner Probleme ist auch, dass du annimmst, ein char* ist gleichbedeutend mit einem String.
Es ist in erster Linie mal so: Ein char* zeigt auf einen char, beeinhaltet also die Speicheraddresse einer char-Variable.
Jetzt können bestimmte Funktionen natürlich vorraussetzen, dass hinter dieser ersten Char-Variable mehr ist.
Ein Beispiel dafür sind Strings: es ist verlangt, dass aller Speicher hinter der ersten char-Variable zugreifbar ist, bis ein 0-Zeichen kommt.

Also mehr kann ich jetzt echt nicht erklärn.......
 
Also tut mir leid, wenn ich Dich nerve!

Also wenn einmal an stelle 450 einen String geschrieben hat, dann bleibt der da die ganze Zeit stehen?

Das heißt, wenn man im Verlauf eines Programms immer andere Strings verwendet, wird immer mehr Speicher gebraucht, weil der Speicher der andreen Strings nicht überschrieben wird?

Also wenn man einem Zeiger einen String zuweißt wird der ganze Speicherbereich durchsucht, und geguckt, ob irgenwo der String steht? Und wenn nicht, wird er neu in den Speicher geschrieben?

Könnte ich denn z.B. den Speicher an dem ein String steht frei machen, damit ich weniger Speicherverbrauch habe, wenn ich den String nicht mehr brauche?

Und wenn man wirklich an die Stelle schreiben will, wo der Zeiger hinzeigt, dann muß man &Zeiger nehmen?
 
Bingo!

Beispiel:
Code:
  char *name = new char[7];
  name[0] = 'l'; name[1] = 'i':name[2] = 'n'; name[3] = 'd'; name[4] = 'i'; name[5] = 'n';
  name[6] = '\0';
  ....

  //ab jetzt brauchst du deinen name nicht mehr und willst den Speicher wieder freigeben
  delete[] name;
  //ab jetzt kannst du dich umbennen
  name = new char[10];
  name[1] = 'A';
  ... //usw

Gruß

RedWing
 
Zuletzt bearbeitet:
Zurück