Forum: Compiler & IDEs Zeiger char - Zeichenketten ersetzen


von C-Beginner (Gast)


Lesenswert?

Hallo Leute,

im Moment beschäftige ich mich gerade mit Zeigern. Leider bin ich auf 
ein Problem gestoßen, dass ich nicht ganz verstehe bzw. wieso es nicht 
so funktioniert. Im Anhang unten ist der C-Code. Egal welche Varianten 
(1-2) ich verwende, meldet der Compiler einen Speicherzugriffsfehler.
Mein Ziel war es, die einzelnen Bustaben von "Hello" durch andere 
Bustaben zu ersetzen. Wenn ich die Variante 3 verwende, dann gibt's 
keine Probleme beim Kompilieren. Woran könnte es liegen?

MfG
1
void main (void)
2
{
3
    char *Text; /* Zeiger vom Typ char */
4
    Text = "Hello";
5
    
6
   /* Variante 1 */
7
   *(Text+0) = 'B';
8
   *(Text+1) = 'e';
9
   *(Text+2) = 'l';
10
   *(Text+3) = 'l';
11
   *(Text+4) = 'o';
12
   *(Text+5) = '\0';
13
14
    /* Variante 2 */
15
    Text[0] = 'B';
16
    Text[1] = 'e';
17
    Text[2] = 'l';
18
    Text[3] = 'l';
19
    Text[4] = 'o';
20
    Text[5] = '\0';
21
   
22
    /* Variante 3 */
23
    Text = "Bello";
24
}

von Karl H. (kbuchegg)


Lesenswert?

Dein ganzes Programm hat undefiniertes Verhalten.

Ein String-Literal (also ein konstanter Text, wie zb "Hello") ist 
unveränderlich! Du darfst gar nicht versuchen, ihn zu ändern.
1
    char *Text; /* Zeiger vom Typ char */
hierdurch hast du einen Zeiger eingerichtet

1
    Text = "Hello";
jetzt lässt du diesen Zeiger auf einen konstanten Text zeigen

1
   *(Text+0) = 'B';
und jetzt versuchst du, über den Zeiger den konstanten Text zu 
verändern. Und das darfst du nicht.


Das geht zwar in C nicht, weil ein Integer-Literal (anders als ein 
String) keine Adresse besitzt. Aber im Grunde, analogiemässig gesehen, 
versuchst du jetzt gerade dieses hier zu machen
1
  int * p;
2
  p = &78;
3
4
  *p = 5;

Deine Variante 3 hingegen, macht etwas ganz anderes. Sie setzt den 
Zeiger um. Der zeigt nicht mehr auf den konstante Text "Hello" sondern 
auf den ebenfalls konstanten Text "Bello"

vorher:
1
   Text
2
   +--------+
3
   |   o-------------------------->"Hello"
4
   +--------+
5
                          "Bello"

nachher
1
   Text
2
   +--------+
3
   |   o--------------+            "Hello"
4
   +--------+         |
5
                      +-->"Bello"

von C-Beginner (Gast)


Lesenswert?

Ich Danke Dir für deine sehr ausführliche Erläuterung. Zu Beginn dachte 
ich, dass durch die Deklaration
1
char *Text = "Hello";
ein veränderbares Char-Array statt eine Stringkonstante erhalte. 
Insbesondere deine Schaubilderchen waren sehr hilfreich. Thx, Karl!

von Karl H. (kbuchegg)


Lesenswert?

C-Beginner schrieb:
> Ich Danke Dir für deine sehr ausführliche Erläuterung. Zu Beginn dachte
> ich, dass durch die Deklaration
>
>
1
> char *Text = "Hello";
2
>
> ein veränderbares Char-Array

Das kann schon deshalb nicht sein, weil in der ganzen Deklaration kein 
Array vorkommt.
Eine Pointer Variable ist immer nur eine Variable, die auf etwas zeigen 
kann. Worauf sie zeigt ... das ist immer davon getrennt.

Keine Sorge: das ist ein weit verbreitetes Misverständnis.

  char Text[] = "Hello";

das sieht zwar fast gleich aus, hat aber einen entscheidenden und 
wichtigen Unterschied: Hier wird Speicher, und zwar veränderbarer 
Speicher, allokiert und dieser Speicher wird mit den Zeichen 'H', 'e', 
'l', 'l', 'o', '\0' initialisiert. Aber grundsätzlich ist dieses Text 
jetzt veränderbar. Du kannst auch einen Pointer darauf einrichten

  char * p = Text;
oder
  char * p = &Text[0];

und dann über den Pointer die Zeichen in Text manipulieren

  *p = 'B';

die Situation im Speicher ist jetzt aber eine ganz andere
1
  p
2
 +-------+
3
 |  o------------------+
4
 +-------+             |  Text
5
                       |  +---+---+---+---+---+---+
6
                       +->| H | e | l | l | o | \0|
7
                          +---+---+---+---+---+---+

von g457 (Gast)


Lesenswert?

> Das kann schon deshalb nicht sein, weil in der ganzen Deklaration kein
> Array vorkommt.

Dem kann man abhelfen:
1
$ cat main.c 
2
#include <stdio.h>
3
4
int main()
5
{
6
        char text[] = "Hallo";
7
8
        printf("original: '%s'\n", text);
9
10
        text[0] = 'B';
11
        text[1] = 'e';
12
        printf("neu: '%s'\n", text);
13
14
        return 0;
15
}
16
$ gcc -Wall -o main main.c
17
$ ./main 
18
original: 'Hallo'
19
neu: 'Bello'

HTH

von Rolf Magnus (Gast)


Lesenswert?

g457 schrieb:
>> Das kann schon deshalb nicht sein, weil in der ganzen Deklaration kein
>> Array vorkommt.
>
> Dem kann man abhelfen:

Wichtige Regel: Bevor man eine Antwort auf ein Posting versendet, sollte 
man es komplett gelesen haben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.