Zeiger char - Zeichenketten ersetzen

Gast #2091258
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
}
#2091267
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"
Gast #2091323
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!
#2091334
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
                          +---+---+---+---+---+---+
Gast #2091351
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren