Warum funktioniert das Einlesen in einen Stringpuffer mit scanf sowohl mit als auch ohne das kaufmännische Und (&)?

Lesezeit: 3 Minuten

abelns Benutzeravatar
abeln

Ich bin etwas verwirrt wegen etwas. Ich hatte den Eindruck, dass die richtige Leseweise eine C-Saite mit einschließt scanf() ging in die Richtung von

(Kümmern Sie sich nicht um den möglichen Pufferüberlauf, es ist nur ein einfaches Beispiel)

char string[256];
scanf( "%s" , string );

Folgendes scheint jedoch auch zu funktionieren,

scanf( "%s" , &string );

Ist das nur mein Compiler (gcc), reines Glück oder etwas anderes?

  • Im zweiten Fall gibt es eigentlich keinen möglichen Pufferüberlauf, da Sie diesen Puffer überhaupt nicht verwenden. Entweder das, oder Sie könnten sagen, dass jede Zeichenfolge, die länger als 3 Zeichen ist, Ihren “Puffer” überlaufen lässt.

    – TED

    23. März 2011 um 15:04 Uhr


  • Ich bezog mich auf das erste Beispiel. Auch andere haben bereits darauf hingewiesen, was hier los ist.

    – abeln

    23. März 2011 um 15:08 Uhr

  • Jawohl. Habe es ausprobiert und Gareth hat Recht. Seltsam.

    – TED

    23. März 2011 um 15:18 Uhr

  • Da diese Frage bei der Suche nach “wie man einen String mit scanf liest” zurückgegeben wird, könnte es angebracht sein, darauf hinzuweisen, dass es bei dieser Frage um Möglichkeiten geht, den Zeiger an den Puffer zu übergeben scanfund sowohl die Frage als auch die akzeptierte Antwort konzentrieren sich darauf und lassen das weg von entscheidender Bedeutung Einschränkungen für die maximale Eingabelänge, die in echtem Code verwendet werden sollten (aber für diese Frage nebensächlich sind).

    – Arkku

    21. September 2018 um 12:10 Uhr


Benutzeravatar von Gareth McCaughan
Gareth McCaughan

Ein Array “zerfällt” in einen Zeiger auf sein erstes Element, also scanf("%s", string) ist äquivalent zu scanf("%s", &string[0]). Auf der anderen Seite, scanf("%s", &string) übergibt einen Zeiger auf-char[256]aber es zeigt auf die gleiche Stelle.

Dann scanfversucht bei der Verarbeitung des Endes seiner Argumentliste, a herauszuziehen char *. Das ist das Richtige, wenn Sie vorbeigekommen sind string oder &string[0]aber wenn du vorbeigekommen bist &string Sie verlassen sich auf etwas, das der Sprachstandard nicht garantiert, nämlich dass die Zeiger &string und &string[0] — Zeiger auf Objekte unterschiedlicher Art und Größe, die an der gleichen Stelle beginnen — werden auf die gleiche Weise dargestellt.

Ich glaube nicht, dass ich jemals auf ein System gestoßen bin, auf dem das nicht funktioniert, und in der Praxis sind Sie wahrscheinlich sicher. Nichtsdestotrotz ist es falsch und könnte auf einigen Plattformen fehlschlagen. (Hypothetisches Beispiel: eine “Debugging”-Implementierung, die Typinformationen mit jedem Zeiger enthält. I denken die C-Implementierung auf den Symbolics “Lisp Machines” hat so etwas gemacht.)

Benutzeravatar von angelita
angelita

Ich denke, dass dies unten richtig ist und es helfen kann. Fühlen Sie sich frei, es zu korrigieren, wenn Sie Fehler finden. Ich bin neu bei C.

char str[]  
  1. Array von Werten vom Typ char mit eigener Adresse im Speicher
  2. Array von Werten vom Typ char, mit eigener Adresse im Speicher so viele aufeinanderfolgende Adressen wie Elemente im Array
  3. einschließlich Abschluss-Nullzeichen '\0' &str, &str[0] und strstellen alle drei dieselbe Stelle im Speicher dar, die die Adresse des ersten Elements des Arrays ist str

    char *strPtr = &str[0]; // Deklaration und Initialisierung

Alternativ können Sie dies in zwei Teile aufteilen:

char *strPtr; strPtr = &str[0];
  1. strPtr ist ein Zeiger auf a char
  2. strPtr zeigt auf Array str
  3. strPtr ist eine Variable mit eigener Adresse im Speicher
  4. strPtr ist eine Variable, die den Wert der Adresse speichert &str[0]
  5. strPtr Die eigene Adresse im Speicher unterscheidet sich von der Speicheradresse, die sie speichert (Adresse des Arrays im Speicher, auch bekannt als &str[0])
  6. &strPtr repräsentiert die Adresse von strPtr selbst

Ich denke, dass Sie einen Zeiger auf einen Zeiger deklarieren könnten als:

char **vPtr = &strPtr;  

deklariert und initialisiert mit der Adresse des strPtr-Zeigers

Alternativ könnte man auch zweiteilen:

char **vPtr;
*vPtr = &strPtr
  1. *vPtr zeigt auf strPtr-Zeiger
  2. *vPtr ist eine Variable mit eigener Adresse im Speicher
  3. *vPtr ist eine Variable, die den Wert der Adresse &strPtr speichert
  4. letzter Kommentar: Sie können nicht tun str++, str Adresse ist A constaber du kannst es tun strPtr++

1424870cookie-checkWarum funktioniert das Einlesen in einen Stringpuffer mit scanf sowohl mit als auch ohne das kaufmännische Und (&)?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy