amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > Pointer-Wunder [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

09.12.2002, 15:00 Uhr

Inferno
Posts: 157
Nutzer
Hallo Programmier-Freunde!

habe mehrere Tage damit zugebracht, einen Fehler zu finden, der regelmäßig zum Absturz führte und hier ist der Wicht: (Storm C 4 unter verschiedenen configs, u.a. WinUAE und "echte" Amigas)

--- snip ---
char buffer[4096];
int index=4;

fillString(index, &buffer[0]);

printf("String is: %s\n", &buffer[0]);
--- /snip ---

Wenn ich dieses Fragment wie folgt ändere, läufts einwandfrei:

--- snip2 ---
char *buffer = new char[4096];
int index=4;

fillString(index, buffer);

printf("String is: %s\n", buffer);
delete[] buffer;
--- /snip2 ---

Könnte es sein, daß er beim & - Operator "relative" Pointer benutzt (da buffer ja auf dem Stack angelegt wird, könnt's relativ zum TopOfStack sein (o.ä.)) ?????

Bin zwar glücklich den Fehler gefunden zu haben, würde aber trotzdem ganz gerne wissen, WARUM die erste Version nicht funktioniert hat !!

Gruß,

Inferno

[ - Antworten - Zitieren - Direktlink - ]

09.12.2002, 15:19 Uhr

Holger
Posts: 8116
Nutzer
Sag lieber, was Deine fillString-Funktion eigentlich macht. Wenn Du über die Array-Grenze hinweg schreibst, überschreibt die erste Variante Deinen Stack (sehr hohe Absturzwahrscheinlichkeit), bei der zweiten Variante fremden Speicher (mittlere Absturzwahrscheinlichkeit).

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

09.12.2002, 15:23 Uhr

Inferno
Posts: 157
Nutzer
Hallo Holger,

die fillString-Routine füllt den buffer mit einem String aus einem Array von Strings (quasi). genaugenommen ist es ein Array von Objekten, die alle einen String* als property haben und fillString nutzt die strcpy - Funktion, um den Inhalt zu kopieren. Dabei bin ich mir aber 100% Sicher, daß keiner der Strings länger als 4096 Bytes ist, das max. ist so um die 50 Bytes ...

Da hatte ich nämlich auch schon dran gedacht, und deshalb hatte ich den buffer entsprechend groß reserviert.

* String = array of chars :-)

Ciao,

Inf!

[ - Antworten - Zitieren - Direktlink - ]

09.12.2002, 18:44 Uhr

thomash
Posts: 172
Nutzer
Hi.

Über das Problem bin ich auch schon mal gestolpert, war aber schon beim Maxon C-Compiler.

Versuchs mal mit

&(buffer[0])

statt

&buffer[0]

dann sollte es gehen.

Es scheint, daß hier Array- und Pointer-Prioritäten kollidieren. Beim alten Aztec C kein Problem, aber je korrekter die Implementation, umso genauer muß der Programmierer schreiben, was er will. :)

Sowieso gilt doch immer: Lieber zu viel klammern, als zu wenig.


Ciao,
Hoin.

[ - Antworten - Zitieren - Direktlink - ]

09.12.2002, 19:56 Uhr

Holger
Posts: 8116
Nutzer
Normalerweise sollte auch einfach nur buffer reichen.

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

10.12.2002, 10:00 Uhr

gni
Posts: 1106
Nutzer
Zitat:
thomash:
&(buffer[0]) statt &buffer[0]

Wo bitte ist der Unterschied?

Zitat:
Es scheint, daß hier Array- und Pointer-Prioritäten kollidieren. Beim alten Aztec C kein Problem, aber je korrekter die Implementation, umso genauer muß der Programmierer schreiben, was er will. :)
So ein Quatsch! Entweder es ist richtig oder es ist falsch.

[ - Antworten - Zitieren - Direktlink - ]

10.12.2002, 10:18 Uhr

thomas
Posts: 7716
Nutzer
Zitat:
Original von gni:
Zitat:
thomash:
&(buffer[0]) statt &buffer[0]

Wo bitte ist der Unterschied?

Bei dem zweiten kommt es darauf an, welche Prioritäten der Compiler setzt. Es könnte auch als (&buffer)[0] interpretiert werden, was etwas völlig anderes ist.



Zitat:
Zitat:
Es scheint, daß hier Array- und Pointer-Prioritäten kollidieren. Beim alten Aztec C kein Problem, aber je korrekter die Implementation, umso genauer muß der Programmierer schreiben, was er will. :)
So ein Quatsch! Entweder es ist richtig oder es ist falsch.

Kein Quatsch. Je nach Compiler werden Ausdrücke unterschiedlich interpretiert. Welcher Compiler dabei fehlerhaft ist, sei mal dahingestellt. Zuviele Klammern machen in jedem Fall Sinn.


Gruß Thomas

--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

10.12.2002, 10:49 Uhr

Inferno
Posts: 157
Nutzer
Hallo!

@thomas:

Danke für den Tipp, werde es mal ausprobieren ... (hatte bisher leider noch keine Zeit dazu) ... und dann hier posten, ob es geholfen hat!

Ciao,

Inf!

[ - Antworten - Zitieren - Direktlink - ]

11.12.2002, 10:40 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von thomas:
Bei dem zweiten kommt es darauf an, welche Prioritäten der Compiler setzt. Es könnte auch als (&buffer)[0] interpretiert werden, was etwas völlig anderes ist.

Eigentlich ist ein array ja nur ein Pointer auf's erste Element. Dann wäre:
  • buffer eben dieser pointer
  • &(buffer[0]) ein pointer auf das erste Element -> dasselbe
  • (&buffer)[0] ein Pointer auf den Pointer, dereferenziert über array index 0 -> wieder der Pointer -> ebenfalls dasselbe

    Wenn da ein Unterschied besteht, werden Arrays völlig anders gehandhabt, ich würde es fehlerhaft nennen.

    mfg

    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

  • 11.12.2002, 13:02 Uhr

    thomas
    Posts: 7716
    Nutzer

    Das ist wahr, wenn der Zeiger als Pointer definiert ist, also char *pointer. Bei einer Array-Definition (char array[]) bekommst du bei &array die Adresse des ersten Elements. Also &array == array == &array[0]. Wenn du es nicht glaubst, probier es aus.

    Gruß Thomas

    --
    Email: thomas-rapp@web.de
    Home: home.t-online.de/home/thomas-rapp/

    [ - Antworten - Zitieren - Direktlink - ]

    11.12.2002, 19:12 Uhr

    thomash
    Posts: 172
    Nutzer
    Hallo Leute,

    bin wieder da. Gestern hatte ich Geburtstag und den Rechner nicht angeschalten, deswegen konnte ich mich nicht wehren. :)

    Der ganze Storm-C V4 macht mir leider keinen sehr guten Eindruck. Ich habe immer irgendwelche nicht nachvollziehbaren Fehlermeldungen, unter anderem auch mit der Pointer/Array-Geschichte.
    Manchmal habe ich Compilerfehler, da muß ich nur eine Zeile löschen und neu eintippen (nein, es war kein Tippfehler drin) und es geht wieder zu übersetzen.
    :dance3:

    Ich vermute, daß der GCC (auch in der Storm-Variante) jeweils andere Übersetzungsmethoden anwendet, je nachdem, ob man für einen String char *
    oder char[] bei der Deklarierung als Datentyp benutzt. Noch leckerer kommt das ganze bei char *-Arrays :rotate: wo ich zum ersten Mal über diese Eigenheit gestolpert bin (lokalisierte Strings als Array...).

    Eigentlich sollte man einen String ja auch nicht verändern, deswegen ist &string[index] schlechter Stil, aber ich benutze es auch gerne, um z.B. einen Shortcut zu überspringen.

    char *kopier = "cCopy";
    puts(&kopier[1]);

    Dieses Fragment gibt dann nur "Copy" aus, man kann aber mit

    char c;
    c = kopier[0];

    einen einzelnen Buchstaben auslesen (hier "c") und z.B. als Menüshortcut verwenden. Aber wehe, es kommt eines Tages Unicode ! :rotate:

    Ich wollte mal vbcc ausprobieren, aber da meine Amigas zur Zeit defekt sind, dauert das noch.

    Naja, frohe Weihnachten noch, falls man sich nicht mehr trifft.

    [ - Antworten - Zitieren - Direktlink - ]

    12.12.2002, 14:10 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von thomash:

    Eigentlich sollte man einen String ja auch nicht verändern, deswegen ist &string[index] schlechter Stil, aber ich benutze es auch gerne, um z.B. einen Shortcut zu überspringen.

    char *kopier = "cCopy";
    puts(&kopier[1]);

    Damit veränderst Du den String nicht, aber übersichtlicher sieht es doch so aus:

    char *kopier = "cCopy";
    puts(kopier+1);

    Oder?
    Zitat:
    Aber wehe, es kommt eines Tages Unicode ! :rotate:
    Das funktioniert exakt genauso, wenn char 2 oder gar 4 bytes lang ist.

    mfg

    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

    12.12.2002, 14:41 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von thomas:
    Das ist wahr, wenn der Zeiger als Pointer definiert ist, also char *pointer. Bei einer Array-Definition (char array[]) bekommst du bei &array die Adresse des ersten Elements. Also &array == array == &array[0]. Wenn du es nicht glaubst, probier es aus.


    Nein.

    Wenn Du ein array benutzt, liefert &array die Adresse des Arrays. Diese Adresse hat dieselbe Position im Speicher wie das erste Element, da C-Arrays ja keine weiteren Daten enthalten als die Elemente. Aber genau deshalb ist ja die Typisierung der Pointer so wichtig. Denn wenn Du den Pointer auf ein Array dereferenzierst, ala (&array)[0] bekommst Du wieder das Array, also den Pointer auf das erste Element, welcher immer noch auf die gleiche Speicherstelle verweist, aber einen anderen Typ hat.

    Du kannst es doch mit einem einfachen Testprogramm sehen
    code:
    #include <stdio.h>
    
    int main(int n, char**a)
    {
      char *s1="Hallo";
      char s2[]={ 'W', 'e', 'l', 't', 0 };
    
      printf("%s ", s1);
      printf("%s.\n", s2);
      printf("s1=%08lx, ", s1);
      printf("&s1=%08lx, ", &s1);
      printf("&(s1[0])=%08lx, ", &(s1[0]));
      printf("(&s1)[0]=%08lx.\n", (&s1)[0]);
      printf("s2=%08lx, ", s2);
      printf("&s2=%08lx, ", &s2);
      printf("&(s2[0])=%08lx, ", &(s2[0]));
      printf("(&s2)[0]=%08lx.\n", (&s2)[0]);
    }

    Der Adresse eines Arrays ist etwas anderes als die Adresse eines Pointers, deshalb verhalten sich &s1 und &s2 auch anders.
    Aber für die Pointer auf die Elemente (alle vom Type char*) spielt das keine Rolle. Zumindest wenn der Compiler keine Fehler hat.

    mfg

    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

    12.12.2002, 19:00 Uhr

    thomash
    Posts: 172
    Nutzer
    Hallo Holger.

    Zitat:
    Original von Holger:
    Damit veränderst Du den String nicht, aber übersichtlicher sieht es doch so aus:

    char *kopier = "cCopy";
    puts(kopier+1);

    Oder?


    Ja, natürlich. Aber es widerstrebt mir noch mehr, einen String wie eine Zahl zu behandeln (Addition), auch wenn ein Pointer eigentlich nichts anderes ist.

    Aber ein Codefragment "kopier + 1" suggeriert unterschwellig und bei oberflächlichem Lesen einen Zahlentyp. Deswegen sollte man eigentlich beide Varianten nicht benutzen. Nur bei meiner kann ich noch erkennen, daß es ein String ist. :)

    Und stell Dir mal vor, irgendwann schreibst Du aus Versehen "kopier++", weils doch auf den ersten Blick dasselbe ist. Nur daß es dabei den Zeiger verbiegt...


    Ciao,
    Hoin.

    [ - Antworten - Zitieren - Direktlink - ]

    13.12.2002, 09:26 Uhr

    gni
    Posts: 1106
    Nutzer
    Zitat:
    thomash:
    Zitat:
    Holger:
    übersichtlicher sieht es doch so aus:
    char *kopier = "cCopy";
    puts(kopier+1);

    Ja, natürlich.
    Nein, aber das ist eine Geschmacksfrage.
    Zitat:
    Und stell Dir mal vor, irgendwann schreibst Du aus Versehen "kopier++", weils doch auf den ersten Blick dasselbe ist. Nur daß es dabei den Zeiger verbiegt...
    Wenn Du das nicht willst, hilft Dir const.

    [ - Antworten - Zitieren - Direktlink - ]

    13.12.2002, 18:53 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von thomash:
    Ja, natürlich. Aber es widerstrebt mir noch mehr, einen String wie eine Zahl zu behandeln (Addition), auch wenn ein Pointer eigentlich nichts anderes ist.

    Tja, und mir widerstrebt es, gerade wenn man in C programmiert (ich vermeide das), eine Operation intuitiver aussehen zu lassen, als es im Endeffekt ist. &a[c] ist in C nichts anderes als a+c und C stellt keinerlei array-Funktionalität zur Verfügung.
    Bei der Additionsschreibweise fällt es viel mehr auf, das c keinerlei Beschränkungen unterworfen ist und man selber aufpassen muß.
    Zitat:
    Nur bei meiner kann ich noch erkennen, daß es ein String ist. :)
    Es ist kein String.
    Zitat:
    Und stell Dir mal vor, irgendwann schreibst Du aus Versehen "kopier++", weils doch auf den ersten Blick dasselbe ist. Nur daß es dabei den Zeiger verbiegt...
    Du meinst a++b statt a+b?
    Haut wohl nicht ganz hin...

    Das der ++ Operator eine gewisse Unübersichtlichkeit besitzt, hat nichts mit Pointer oder nicht Pointer zu tun. Das gilt für Integer-Werte genauso.

    mfg

    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ Dieser Beitrag wurde von Holger am 13.12.2002 editiert. ]

    [ - Antworten - Zitieren - Direktlink - ]


    -1- [ - Beitrag schreiben - ]


    amiga-news.de Forum > Programmierung > Pointer-Wunder [ - Suche - Neue Beiträge - Registrieren - Login - ]


    .
    Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
    Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
    .