Pointer incrementieren schlägt fehl?!

OP #5112745
Hallo.

Auf nem MEGA32 klappt es, nur auf dem Rechner nicht. Es wird nichts 
angezeigt. Wieso?
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4

5
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
6

7

8

9
void ausgabe(char *str){
10
  
11
  int x = 0;
12
  
13
  *str++ = 'A';
14
  *str++ = 'B';
15
  *str++ = 'C';
16
  
17
  //str[x++] = 'A';
18
  //str[x++] = 'B';
19
  //str[x++] = 'C';
20
  
21
  printf(str);
22
}
23

24

25
int main(int argc, char *argv[]) 
26
{
27
  char *buff = (char*)calloc(11,sizeof(char));
28
  ausgabe(buff);
29

30
  return 0;
31
}
Für printf und andere String-Fkt. würde ich einen String auch imemr mit 
'\0' abschliessen.

Würde mich wundern wenn genau der Source aufm µC läuft.
FEHLER beim Copy&Paste ? ;-)

Versuch das:
1
void ausgabe(char *str){
2
  
3
  char *tmp = str;
4

5
  *tmp++ = 'A';
6
  *tmp++ = 'B';
7
  *tmp++ = 'C';
8
  *tmp   = '\0';
9
 
10
  printf(str);
11
}
Gast
Tipp am Rande: Bei der Inkrementierungs-Dereferenzierungs-Geschichte 
Klammern setzen. Dann ist auf Anhieb klar was deine Intention war und 
was der Code macht wenn man die C Operator Precedence gerade nicht parat 
hat ;)
Gast
Mit dem Verändern von Parametern innerhalb einer Funktion kann man sich 
wie man hier sieht sehr elegant und effizient selbst hereinlegen.
1
void ausgabe(char *str)
2
{
3
    char* write_cursor = str;
4
    *write_cursor++ = 'A';
5
    *write_cursor++ = 'B';
6
    *write_cursor++ = 'C';
7
     
8
    printf(write_cursor);
9
}
In dieser Version wäre der Fehler offensichtlich gewesen. 'str' ist im 
Hinterkopf als "der String, in den ich schreibe" abgelegt. Wenn man den 
String am Ende der Funktion ausgeben will, liegt 'printf(str)' nahe; 
dass man 'str' vorher verändert hat, hat man an der Stelle leicht schon 
wieder vergessen.
Jan,
du kannst es aber auch so machen:
1
void ausgabe(char *str)
2
{
3
  str[0] = 'A';
4
  str[1] = 'B';
5
  str[2] = 'C';
6
 
7
  printf(str);
8
}

...gibt 1000 Wege.


edit:
Ah, so hattest du es wohl schon mal - jedoch auskommentiert. OK.
Gast
Jan H. schrieb:
> char *buff = (char*)calloc(11,sizeof(char));

sizeof(char) ist per Definition immer 1. Du kannst also einfach 
calloc(11,1) oder noch einfacher malloc(11) schreiben. Der Grund ist, 
dass sizeof die Größe des Typs als Vielfache von der Größe von "char" 
zurückgibt, und "char" ist nunmal genau 1 char groß, also ist es immer 
1. (Siehe z.B. http://en.cppreference.com/w/c/language/sizeof )

Der Cast nach char* ist übrigens in C nicht nötig, nur in C++ - aber da 
würde man onehin lieber "new" nutzen.
OP
Habe das gerade mal ausprobiert.
Da stürzt die .exe ab.
1
void ausgabe(char *str)
2
{
3
    char* write_cursor = str;
4
    *write_cursor++ = 'A';
5
    *write_cursor++ = 'B';
6
    *write_cursor++ = 'C';
7
     
8
    printf(write_cursor);
9
}
10

11
int main(int argc, char *argv[]) {
12
  
13
  ausgabe("WIRD EH NICHT BENUTZT^^");
14
  
15
  return 0;
16
}
Gast
Jan H. schrieb:
> Habe das gerade mal ausprobiert.
> Da stürzt die .exe ab.

ja, weil du versucht einen kontante, die im nicht schreibbaren Speicher 
steht zu überschreiben. Das würde auf einen µC funktionieren, auf den 
meisten PCs nicht mehr.
Es ist doch immer wieder Interessant, wie viele Fehler man in so wenig 
Zeilen machen kann.

Interessant ist auch, dass das ganze auf 'nem Mega32 geklappt haben 
soll.


Da war doch irgendwo eine uralte Schwarte mit den Grundlagen zu "C".

Oder kann es sein, dass man so etwas heute nicht mehr braucht?

Also ich würde sagen man kann den Ansatz: "Learning by doing" auch 
übertreiben.
Adam P. schrieb:
> Versuch das:
>
>
1
> void ausgabe(char *str){
2
> 
3
>   char *tmp = str;
4
> 
5
>   *tmp++ = 'A';
6
>   *tmp++ = 'B';
7
>   *tmp++ = 'C';
8
>   *tmp   = '\0';
9
> 
10
>   printf(str);
11
> }
12
>

In der Praxis würde ich jeweils noch die Länge des reservierten 
Speichers für die Zeichenkette mitgeben und beachten. Ansonsten kann es 
bei späteren Anpassungen und Unachtsamkeit durch einen selbst oder 
andere Entwickler schnell mal passieren, dass man über den reservierten 
Speicher hinaus schreibt und es dann zu nicht gewolltem Verhalten führen 
kann, welches nur sehr mühsam aufzuspüren ist.
Reinhold schrieb:
> Tipp am Rande: Bei der Inkrementierungs-Dereferenzierungs-Geschichte
> Klammern setzen.

Der Ausdruck *str++ ist derart grundlegend für C, dass ich geradezu 
davon abraten würde, dort Klammern zu setzen. Sondern raten würde, zu 
verstehen, warum das so funktioniert.

An dieser Stelle Klammern zu setzen sorgt eher für Erheiterung 
erfahreneren Publikums als für Verständnis beim Lesen.

Es gibt gute Gründe dafür, solche Seiteneffekt-Operationen abzulehnen, 
unbeschadet des intuitiven oder unintuitiven Vorrangs der Operatoren. 
Aber dann richtig. Also
  *str = 'A'; str += 1;
  *str = 'B'; str += 1;
um Diskussionen zu vermeiden, was bei
  *str++ = *str++ = *str++ = 0;
alles rauskommen kann. ;-)
Gast
Reinhold schrieb:
> Tipp am Rande: Bei der Inkrementierungs-Dereferenzierungs-Geschichte
> Klammern setzen. Dann ist auf Anhieb klar was deine Intention war und
> was der Code macht wenn man die C Operator Precedence gerade nicht parat
> hat ;)

wir würdest du denn die Klammern setzen wollen?

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.