amiga-news DEUTSCHE VERSION
.
Links| Forums| Comments| Report news
.
Chat| Polls| Newsticker| Archive
.

amiga-news.de Forum > Programmierung > Pointer-Wunder [ - Search - New posts - Register - Login - ]

-1- [ - Post reply - ]

2002-12-09, 15:00 h

Inferno
Posts: 157
User
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: %sn", &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: %sn", 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

[ - Answer - Quote - Direct link - ]

2002-12-09, 15:19 h

Holger
Posts: 8116
User
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.

[ - Answer - Quote - Direct link - ]

2002-12-09, 15:23 h

Inferno
Posts: 157
User
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!

[ - Answer - Quote - Direct link - ]

2002-12-09, 18:44 h

thomash
Posts: 172
User
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.

[ - Answer - Quote - Direct link - ]

2002-12-09, 19:56 h

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

mfg

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

[ - Answer - Quote - Direct link - ]

2002-12-10, 10:00 h

gni
Posts: 1106
User
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.

[ - Answer - Quote - Direct link - ]

2002-12-10, 10:18 h

thomas
Posts: 7718
User
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/

[ - Answer - Quote - Direct link - ]

2002-12-10, 10:49 h

Inferno
Posts: 157
User
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!

[ - Answer - Quote - Direct link - ]

2002-12-11, 10:40 h

Holger
Posts: 8116
User
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.

    [ - Answer - Quote - Direct link - ]

  • 2002-12-11, 13:02 h

    thomas
    Posts: 7718
    User

    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/

    [ - Answer - Quote - Direct link - ]

    2002-12-11, 19:12 h

    thomash
    Posts: 172
    User
    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.

    [ - Answer - Quote - Direct link - ]

    2002-12-12, 14:10 h

    Holger
    Posts: 8116
    User
    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.

    [ - Answer - Quote - Direct link - ]

    2002-12-12, 14:41 h

    Holger
    Posts: 8116
    User
    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.

    [ - Answer - Quote - Direct link - ]

    2002-12-12, 19:00 h

    thomash
    Posts: 172
    User
    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.

    [ - Answer - Quote - Direct link - ]

    2002-12-13, 09:26 h

    gni
    Posts: 1106
    User
    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.

    [ - Answer - Quote - Direct link - ]

    2002-12-13, 18:53 h

    Holger
    Posts: 8116
    User
    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. ]

    [ - Answer - Quote - Direct link - ]


    -1- [ - Post reply - ]


    amiga-news.de Forum > Programmierung > Pointer-Wunder [ - Search - New posts - Register - Login - ]


    .
    Masthead | Privacy policy | Netiquette | Advertising | Contact
    Copyright © 1998-2024 by amiga-news.de - all rights reserved.
    .