Frage zu Zeiger
-
Heimelchen schrieb:
... den andern nicht.
falsch.
mfg
-
Hallo zusammen,
char *buff = "abc";
und
char buff[] = "abc";
sind gleichwertig.
Wenn man die Zeichen jedoch nicht verändern will sollte man
das mit einem 'const' deulich machen.Da man sowieso nur begrentzt Änderungen an den Zeichen machen kann,
in diesem Fall 3 + 1 Zeichen Zeichen, macht diese Schreibweise in den wenigsten Fällen überhaupt Sinn - ausser man will sich tipparbeit sparen.kurz:
const char *buff = "abc";
ist das wie ich es normalerweise verwende.
Zeiger sind die 'Macht' bei C. Hiermit sind super flotte und generische Programme möglich. Leider ist es auch ein Vergleichsweise schweres Thema mit vermutlich den meisten Fehlerquellen und den mit Sicherheit 'übelsten' Fehlerbildern. Richtig intressant sind dann Funktionszeiger ...
Viel Spass noch mit dem Thema,
Gruß Frank
-
#include <stdio.h> int main(void) { char buf[] = "foobar"; char const *ptr = "foobar"; printf("%d != %d\n", sizeof(buf), sizeof(ptr)); return 0; }
Jedes mal, wenn jemand ein String-Literal einem char* zuweist, stirbt ein niedliches Kätzchen auf grausame Weise. Aber const oder nicht const, ein Zeiger ist kein Array!
-
hm, zwei gegensätzliche meinungen. das beides übersetzt wird und das gleich ergebniss liefert, könnte man in einem kleinen test nachvollziehen, aber ob da im zweifelsfall compilerinterne unterschiede bestehen, würde mich schon interessieren.
-
Hallo zusammen,
seldon hat recht,
bei der array Schreibweise kann man die 'size' noch zur Kompilezeit ermitteln.
Das habe ich bisher übrigends noch nie verwendet ...Gruß Frank
-
Hallo Vector von Doom,
kompilier doch mal das Beispiel von seldon
und schau dir den Assembler Code an, wenn es dich soo intressiert ...Gruß Frank
-
Der wesentliche Unterschied in diesem Fall ist, dass der Zeiger nach
char *buf = "foo"; /* Brzzzzz! MIAUUU! */
nicht auf einen Buffer zeigt, sondern auf ein String-Literal, welches nicht dir gehört und in welchem du nicht rumschreiben darfst. Dagegen erzeugt
char buf[] = "foo";
einen Buffer von vier Zeichen Länge auf dem Stack, der dir gehört und mit dem du machen darfst, wozu du lustig bist.
Ein Zeiger zeigt. Ein Buffer beinhaltet. Völlig unterschiedliche Dinge.
-
besserwisser schrieb:
Heimelchen schrieb:
... den andern nicht.
falsch.
mfgDen Zeiger kann man natürlich ändern, aber nicht den Inhalt! Ich wette, dass das Beispiel auch eine warnung erzeugt.
-
seldon schrieb:
Der wesentliche Unterschied in diesem Fall ist, dass der Zeiger nach
char *buf = "foo"; /* Brzzzzz! MIAUUU! */
nicht auf einen Buffer zeigt, sondern auf ein String-Literal, welches nicht dir gehört und in welchem du nicht rumschreiben darfst.
das hat mein prof so oder so ähnlich auch gesagt.
#include <stdio.h> int main() { char *buf = "foo"; /* Brzzzzz! MIAUUU! */ printf(buf); *buf = 'b'; *(buf+1) = 'a'; *(buf+2) = 'r'; printf(buf); return 0; }
wird trotzdem übersetzt und "foobar" ausgeben.jetzt würde mich mal interessieren, wie der kompiler sowas regelt.
int main() { char *buf = "foo"; /* Brzzzzz! MIAUUU! */ char puf[] = "foo"; printf("\n%p", buf); printf("\n%p", puf); return 0; }
zeigt, dass buf und puf nicht direkt hintereinander liegen. liegt das eine auf dem stack und das andere auf dem heap?
-
Hallo Vector,
String Literale liegen im statischen Speicher
Beispiel
char *buf1 = "foo"; /* Brzzzzz! MIAUUU! */ char *buf2 = "foo"; /* Brzzzzz! MIAUUU! */
Hier optimieren viele compiler und legen "foo" nur einmal ind den
statischen Speicher. buf1 und buf2 beinhalten dann gleichen Adressen auf den selben statischen Speicher.
Ich kenne Compiler, die so etwas machen.
Gleiches gilt auch für Zahlen 'Konstanten',
hier kommt ja auch niemand auf die idee soetwas zu schreiben:int* pInt = &5; *pInt = 4; // prost mahlzeit!
Wobei der Kompiler den ersten Fall merken könnte,
anwarnen oder eben eine neuen statischen Speicher anlegen könnte,
so daß nur bei folgender Konstellation:const char *buf1 = "foo"; const char *buf2 = "foo";
buf1 und buf2 die gleichen Adressen haben.
Und ja, ich glaube auch
char puf[] = "foo";
sind 4 chars "foo\0" auf dem Stack und puf zeigt darauf.
Und nein, auf dem Heap liegt nichts von deinem Beispiel,
heap bekommst du mit malloc ...Gruß Frank
edit sieht der Vergleich mit einer Zahlen Konstante hinkt,
was soll's
-
vector schrieb:
#include <stdio.h> int main() { char *buf = "foo"; /* Brzzzzz! MIAUUU! */ printf(buf); *buf = 'b'; *(buf+1) = 'a'; *(buf+2) = 'r'; printf(buf); return 0; }
wird trotzdem übersetzt und "foobar" ausgeben.jetzt würde mich mal interessieren, wie der kompiler sowas regelt.
Stringliterale landen normalerweise im DATA-Segment oder wie auch immer das jeweilige BS diesen Teil nennt. Das ist grundsätzlich für die Anwendung beschreibbar und wird auch für jede Instanz der Anwendung neu angelegt.
Der ANSI-Standard erlaubt aber auch, STRING-Literale in einem nicht beschreibbaren Teil der Anwendung abzulegen. Moderne BS und Compiler sollten das auch können, ich weiß aber nicht, ob Windows oder Linux dazu gehören.
Auf jeden Fall ist das eine tickende Zeitbombe.
vector schrieb:
int main() { char *buf = "foo"; /* Brzzzzz! MIAUUU! */ char puf[] = "foo"; printf("\n%p", buf); printf("\n%p", puf); return 0; }
zeigt, dass buf und puf nicht direkt hintereinander liegen. liegt das eine auf dem stack und das andere auf dem heap?
buf zeigt auf einen Speicher, der nicht auf dem Stack liegt. Das kann der heap sein, aber auch was anderes. puf ist auf jeden Fall ein Speicher auf dem Stack. Der muß auf jeden Fall erstmal initialisiert werden. Wie der Compiler das realisiert, bleibt ihm überlassen. Sowas könnte dabei herauskommen:
DATA _foo: "foo\0" CODE main: register1 = &_foo; stackPointer -= 4; call strcpy( stackPointer, &_foo );
oder auch
DATA _foo: "foo\0" CODE main: register1 = &_foo; stackPointer -= 4; stackpointer[0] = 'f'; stackpointer[1] = 'o'; stackpointer[2] = 'o'; stackpointer[3] = 0;
Ich hoffe mein Pseudocode ist einigermassen verständlich.
Macht Euch mal nicht zu viele Gedanken, wie Compiler mit Stringliteralen umgehen. Sie dürfen nicht verändert werden und damit basta. Alles andere verleitet nur Code zu schreiben, der (irgendwanneinmal) nicht funktioniert.
mfg Martin
-
Die frage habe ich hier auch mal gestellt das ist mein Quelltext. ^^
Den hast du wohl hier im Forum gefunden. ^^
-
vector schrieb:
#include <stdio.h> int main() { char *buf = "foo"; /* Brzzzzz! MIAUUU! */ printf(buf); *buf = 'b'; *(buf+1) = 'a'; *(buf+2) = 'r'; printf(buf); return 0; }
wird trotzdem übersetzt und "foobar" ausgeben.jetzt würde mich mal interessieren, wie der kompiler sowas regelt.
Wenn das auch läuft, es ist nicht richtig. Spätestens wenn du so einen Code in einen Controller laden willst, ist "foo" eine Konstante und kann nicht geändert werden.