C-Programm: Speicherzugriffsfehler bei Zeichenreihenverknuepfung
-
Hallo liebes Forum,
Lt. Büchlein macht die Funktion *strcat der Bibliothek <string.h> folgendes:
Prototyp: char *strcat (char *s1, const char *s2);
Beschreibung: "Fuegt eine Kopie der Zeichenfolge s2 an das Ende der Zeichenfolge s1 an, wobei das erste Zeichen von *s2 das abschliessende '\0'-Zeichen von *s1 ueberschreibt. Der Funktionswert ist der Zeiger s1."
- So weit, so gut (oder auch nicht). Kann mir jemand verraten, warum ich dann mit dem folgenden Programm einen "Speicherzugriffsfehler" erhalte, wenn ich es ausfuehre?!
#include <string.h> int main () { char* s = strcat("x", "y"); printf("string: %s", s); return 0; }
Ich habe es auch mit expliziter Deklaration von Zeigern auf Zeichenreihen versucht, aber es klappt nicht (gleiche Fehlermeldung):
#include <string.h> int main () { char* x = "x"; char* y = "y"; char* s = strcat(x, y); printf("string: %s", s); return 0; }
Kann jemand mir den Grund bzw. "Trick" verraten?
Und: gibt es in C (nicht C++) eine Moeglichkeit, Zeichenreihen "schneller" zu verknuepfen (andere Syntax, z.B. wie in Java: s = x+y oder ähnlich)? Bei einer "Einklammerung" einer Zeichenreihe S in "(" + S + ")" sieht das mit o.g. Funktion schon recht unuebersichtlich aus?
Im Voraus bereits vielen Dank fuer einen hilfreichen Tipp!
-
Solange dein String nicht dynamisch sein soll, vergib eine feste größe:
#include <stdio.h> #include <string.h> int main(void) { char s[5] = "x "; strcat(s, "Y"); printf("string: %s",s); return 0; }
-
Die Funktion strcat hängt den zweiten String an den ersten an. In deinem Codebeispiel ist im ersten String aber nicht genügent Platz. Insgesamt müssen in den String x drei Chars passen 'X','Y' und '\0'. Das ist bei dir nicht der Fall. Um das Probelm zu lösen musst du von Anfang an dem String x genügend Platz reservieren. Wie das funktioniert siehst du im Beispiel von Doc s.
-
Hallo Doc S und Amtrak,
Vielen Dank fuer Eure Antworten, sie haben mir weitergeholfen!!
Ich glaube, der Grund fuer den Speicherzugriffsfehler ist der folgende: Bei einer char*-Deklaration mit einer Zuweisung eines Strings durch bspw.
char *t = "abc"
wird "abc" als Konstante (!) eingefuehrt. Diese kann nicht geaendert werden, insbesondere kann nicht das '\0' am Ende des Strings entfernt werden. Somit kann der Zeiger t nicht an strcat() uebergeben werden (siehe Prototyp in meinem ersten Posting) bzw. die Funktion liefert einen Speicherzugriffsfehler.
Ich gebe einfach mal ein Beispiel an (erste Variablendeklaration etwas verspielt
):
#include <string.h> int main () { /* OK: */ char *t; t = (char *)malloc(2 * sizeof(char) + sizeof('\0')); t[0] = 'a'; t[1] = 'b'; t[2] = '\0'; /* * t = "ab"; -> erzeugt Fehler, da "ab" konstant! */ strcat(t, "x"); printf("string: %s", t); return 0; }
Liege ich da richtig?
Viele Gruesse,
Flachkoepper
-
Flachkoepper schrieb:
Ich glaube, der Grund fuer den Speicherzugriffsfehler ist der folgende: Bei einer char*-Deklaration mit einer Zuweisung eines Strings durch bspw.
char *t = "abc"
wird "abc" als Konstante (!) eingefuehrt. Diese kann nicht geaendert werden, insbesondere kann nicht das '\0' am Ende des Strings entfernt werden.
So ist es.
Ich gebe einfach mal ein Beispiel an (erste Variablendeklaration etwas verspielt
):
#include <string.h>
#include <stdlib.h>
fehlt, wegen malloc.
int main () { /* OK: */ char *t; t = (char *)malloc(2 * sizeof(char) + sizeof('\0'));
Das sieht so etwas seltsam aus, niemand würde das so schreiben. Kanonisch wäre etwa:
t = malloc(3*sizeof(*t));
Warum? Es ist generell etwas ungeschickt, mit sizeof(typ) zu arbeiten, weil man dann, wenn man den Typ von der Variable mal ändern sollte, das 'typ' überall von Hand ändern muß. Dieses Problem fällt bei meiner Variante weg. Zweitens ist sizeof('\0') in C das gleiche wie sizeof(int), nicht das gleiche wie sizeof(char), wie man erwarten könnte; in C++ ist das anders. Verwendest Du einen C++-Compiler? Der Cast vor dem malloc läßt das vermuten.
t[0] = 'a'; t[1] = 'b'; t[2] = '\0';
Normalerweise schreibt man strcpy(t, "ab).
/* * t = "ab"; -> erzeugt Fehler, da "ab" konstant! */ strcat(t, "x"); printf("string: %s", t); return 0; }
Das Programm ist so falsch, auch wenn es vermutlich nicht abstürzt, weil auf deinem System sizeof(int)==sizeof('\0') 4 Byte groß sein dürfte.
Wenn Du strcat(t, u) verwendest, dann muß t auf einen Speicherbereich zeigen, der Platz hat für strlen(t)+strlen(u)+1 Zeichen, bei dir also 2+1+1=4 Zeichen, also oben: 't = malloc(4*sizeof(*t))'. In C muß man immer den Speicherbereich für alles mögliche selbst zur Verfügung stellen, das macht in C das Programmieren häufiger etwas unbequem, aber man gewöhnt sich daran.
-
So in etwa hast du Recht. Wenn du einen char Zeiger mit einem String Literal initialisierst z.B.
char *s = "Literal";
legt der Compiler diesen als Konstante in einem read-only Speicher ab. Wenn du jetzt versuchst diese Konstante zu verändern z.B
*s = 'M';
kann es auf manchen Systemen zu einem Laufzeitfehler kommen.
Wenn du allerdings eine Array-Variable mit einem String Literal initialisierts z.B.
char s[] = "Literal"
kannst du den String nachher noch ändern
s[0] = 'M';
, da er nicht in einem read-only Speicher abgelegt ist.