Dynamisches Array (realloc)



  • ACYROL schrieb:

    habe das casten natürlich auch noch entfernt, geht aber auch mit

    gehen tut vieles erstmal, aber manches sollte man sich gar nicht erst angewöhnen.
    🙂


  • Mod

    Ramsis schrieb:

    ++anzahl;
    PZA = (unsigned long int *) realloc(PZA, anzahl * sizeof(unsigned long int));
    

    Ein schönes Leck. realloc gibt den ursprünglichen Speicher - richtigerweise - nicht frei, wenn die Allokation eines größeren Blockes fehlschlägt.

    Swordfish schrieb:

    Das Ergebnis von malloc und realloc bitte nicht casten.

    Begründung? Ich hatte eigentlich den Eindruck, dass das zum guten Stil gehört.



  • camper schrieb:

    Swordfish schrieb:

    Das Ergebnis von malloc und realloc bitte nicht casten.

    Begründung? Ich hatte eigentlich den Eindruck, dass das zum guten Stil gehört.

    guckst du diesen thread: http://www.c-plusplus.net/forum/viewtopic-var-t-is-204733-and-highlight-is-gewollt.html
    (am ende etwa)
    🙂



  • camper schrieb:

    realloc gibt den ursprünglichen Speicher - richtigerweise - nicht frei, wenn die Allokation eines größeren Blockes fehlschlägt.

    Da er sein Programm beim Fehlschlag sowieso abschießt hab' ich mir es erspart, ihn darauf aufmerksam zu machen. Aber Du hast natürlich recht.

    Swordfish schrieb:

    Das Ergebnis von malloc und realloc bitte nicht casten.

    Begründung? Ich hatte eigentlich den Eindruck, dass das zum guten Stil gehört.[/quote]
    Ist deine Frage ernstgemeint?

    greetz, Swordfish


  • Mod

    verlinkungs-freak schrieb:

    camper schrieb:

    Swordfish schrieb:

    Das Ergebnis von malloc und realloc bitte nicht casten.

    Begründung? Ich hatte eigentlich den Eindruck, dass das zum guten Stil gehört.

    guckst du diesen thread: http://www.c-plusplus.net/forum/viewtopic-var-t-is-204733-and-highlight-is-gewollt.html
    (am ende etwa)
    🙂

    ich antworte trotzdem mal hier:

    1. Das ist doch eher ein Grund, es gerade zu tun: ein Zeiger, der nicht void* ist, kann nicht implizit in einen Zeiger auf einen anderen Typ (außer void*) konvertiert werden, kann also nicht an Zeiger des falschen Typs zugewiesen werden.
      Eine korrekte Allokation hat ja im Allgemeinen die Form:
    p = (T*)malloc( x * sizeof( T ) );
    

    Der Compiler hat keine Möglichkeit festzustellen, ob der sizeof Ausdruck stimmt, wohl aber, ob der Zeigertyp nach dem Casten passt. Für den Programmierer wiederum ist es leicht, zu erkennen, ob cast und sizeof-Ausdruck zueinander passen, da diese optisch fast identisch sind. Das Beispiel im folgenden Post ist sowieso Mist. Irgendetwas Absurdes als Gegenbeispiel für goldene Regeln fällt mir noch immer ein.
    2) Das stimmt wohl, eine der schlimmeren Eigenschaften von C - andererseits wird ein anständiger Compiler bei Verwendung undeklarierter Funktionen immer warnen; dem ist mit gutem Stil ohnehin nich geholfen, wer solche Warnungen ignoriert.
    3) kein richtiger Grund.



  • camper schrieb:

    Ramsis schrieb:

    ++anzahl;
    PZA = (unsigned long int *) realloc(PZA, anzahl * sizeof(unsigned long int));
    

    Ein schönes Leck. realloc gibt den ursprünglichen Speicher - richtigerweise - nicht frei, wenn die Allokation eines größeren Blockes fehlschlägt.

    Auf die Fehlerbehandlung hab ich verzichtet und den Speicher am Ende wieder frei zu geben.
    Habe nur eine Lösung für ein Problem gelifert. ACYROL hat eine Fehlerbehandlung in seiner Anwendung, also weiss er bescheid. 😃



  • Swordfish schrieb:

    Ist deine Frage ernstgemeint?

    wieso sollte er sie nicht ernst meinen? verdammt viele machen den malloc-cast fehler. mir fielen auch die schuppen aus den haaren, als ich zum ersten mal gehört habe, dass 'malloc casten' nicht gut ist.
    🙂


  • Mod

    Swordfish schrieb:

    Ist deine Frage ernstgemeint?

    Absolut. Ich bevorzuge C++, bin da also nicht ganz unvoreingenommen - insofern lasse ich mich also gerne etwas Besseren belehren.

    Edit: Meine Argumentation ist wahrscheinlich auch nicht so überzeugend, ein erfahrenen Programmierer wird einen Ausdruck - *p - an Stelle eines Types bevorzugen - dann bedarf es keiner Prüfung und man kann auch das Casten unterlassen. So oder so kann ich keine Präferenz pro oder contra cast ableiten - lediglich für den Fall, dass ein Stück Code sowohl unter C als auch unter C++ laufen soll, müssen wir natürlich casten.



  • camper schrieb:

    Eine korrekte Allokation hat ja im Allgemeinen die Form:

    p = (T*)malloc( x * sizeof( T ) );
    

    Der Compiler hat keine Möglichkeit festzustellen, ob der sizeof Ausdruck stimmt, wohl aber, ob der Zeigertyp nach dem Casten passt. Für den Programmierer wiederum ist es leicht, zu erkennen, ob cast und sizeof-Ausdruck zueinander passen, da diese optisch fast identisch sind.

    gutes argument, aber mir ist es tatsächlich schon passiert, dass ich schrieb:
    char i = (char)malloc(100); (einfach nur die sternchen vergessen). hätte ich char i = (char)malloc(100sizeof(char));* geschrieben, hätte es nicht viel geholfen, selbst wenn ich das '*' im sizeof doch hingeschrieben hätte. grundsätzlich sollte man sowieso nur casten, wenn es unausweichlich ist. ein cast vor einem malloc-aufruf killt nun mal jede information, auch die, dass es sich um einen (typlosen) pointer handelt.
    🙂



  • camper schrieb:

    ...lediglich für den Fall, dass ein Stück Code sowohl unter C als auch unter C++ laufen soll, müssen wir natürlich casten.

    ach quark, da jage ich lieber den C code durch einen 'echten' C-compiler und überlasse dem linker alles weitere.
    🙂


  • Mod

    void*-freak schrieb:

    camper schrieb:

    Eine korrekte Allokation hat ja im Allgemeinen die Form:

    p = (T*)malloc( x * sizeof( T ) );
    

    Der Compiler hat keine Möglichkeit festzustellen, ob der sizeof Ausdruck stimmt, wohl aber, ob der Zeigertyp nach dem Casten passt. Für den Programmierer wiederum ist es leicht, zu erkennen, ob cast und sizeof-Ausdruck zueinander passen, da diese optisch fast identisch sind.

    gutes argument, aber mir ist es tatsächlich schon passiert, dass ich schrieb:
    char i = (char)malloc(100); (einfach nur die sternchen vergessen). hätte ich char i = (char)malloc(100sizeof(char));* geschrieben, hätte es nicht viel geholfen, selbst wenn ich das '*' im sizeof doch hingeschrieben hätte. grundsätzlich sollte man sowieso nur casten, wenn es unausweichlich ist. ein cast vor einem malloc-aufruf killt nun mal jede information, auch die, dass es sich um einen (typlosen) pointer handelt.
    🙂

    Die Möglichkeit habe ich erwogen, aber wie wahrscheinlich ist es, dass du mit dem char i, dass eigentlich ein Zeiger sein soll, weiterarbeiten kannst, ohne fürher oder später über einen Compilerfehler wegen Dereferenzierung zu stoßen?

    Grundsätzlich ist es richtig, Redundantes zu vermeiden - der größte Fehlerquelle bei malloc&co. ist die Anforderung einer falschen Menge an Speicher und der Compiler kann uns dabei nicht direkt helfen, folglich ist eine stilistische Regel dort angebracht. Damit ergeben sich (unter Beachtung des zuvor gesagten) zwei kanonische Möglichkeiten:

    p = malloc( x * sizeof *p );
    p = (T*)malloc( x * sizeof ( T ) );
    

    bei der ersten Variante gibt es im Grunde keine besonderen Fehlerquellen, bei der zweiten setzen wir nur auf Optik, diese ist also schlechter, hat dafür aber den Vorteil der Kompatibilität mit C++ (oder Uralt C-Compilern) wo dies eine Rolle spielt.



  • camper schrieb:

    Damit ergeben sich (unter Beachtung des zuvor gesagten) zwei kanonische Möglichkeiten:

    p = malloc( x * sizeof *p );
    p = (T*)malloc( x * sizeof ( T ) );
    

    bei der ersten Variante gibt es im Grunde keine besonderen Fehlerquellen...

    klar gibt's die. wenn p selber ein void* ist, dann haut
    *p = malloc( x * sizeof p );
    nicht hin. und was die kompatibilität zu C++ angeht: besser ist es, wenn C code durch einen C-compiler geht, C++-code durch einen C++ compiler und der linker alles zusammenfügt (siehe oben). es gibt noch viele andere unverträglichkeiten zwischen C und C++ --> http://david.tribble.com/text/cdiffs.htm
    🙂


  • Mod

    c-freak schrieb:

    camper schrieb:

    Damit ergeben sich (unter Beachtung des zuvor gesagten) zwei kanonische Möglichkeiten:

    p = malloc( x * sizeof *p );
    p = (T*)malloc( x * sizeof ( T ) );
    

    bei der ersten Variante gibt es im Grunde keine besonderen Fehlerquellen...

    klar gibt's die. wenn p selber ein void* ist, dann haut
    *p = malloc( x * sizeof p );
    nicht hin.

    Stimmt, eine mögliche Fehlerquelle, aber keine besonders Wichtige, denn der Compiler muss darüber stolpern, kein Widerspruch also.
    Es gibt solche Speicheranforderungen, die nicht obiger Form genügen können, aber in solchen Fällen ist die Aufmerksamkeit ohnehin größer und es bedarf nicht unbedingt irgendwelcher Stilregeln. Solche Regeln existieren schließlich, Fehler, die wegen mangelnder Aufmerksamkeit entstehen können, zu vermeiden oder einzudämmen. Gegen Machiavelli ist ohnehin kein Kraut gewachsen.

    und was die kompatibilität zu C++ angeht: besser ist es, wenn C code durch einen C-compiler geht, C++-code durch einen C++ compiler und der linker alles zusammenfügt (siehe oben). es gibt noch viele andere unverträglichkeiten zwischen C und C++ --> http://david.tribble.com/text/cdiffs.htm
    🙂

    Wurde bereits erwähnt, und ich habe auch nicht widersprochen. Eine Wiederholung gibt diesem Argument nicht mehr Gewicht. Es gibt Code, der unter beiden Sprachen arbeiten muss und in vielen Fällen (selbstverständlich gibt es Ausnahmen) resultiert der Versuch, diese Kompatibilität zu erreichen, in besserem Stil.



  • camper schrieb:

    Es gibt Code, der unter beiden Sprachen arbeiten muss und in vielen Fällen (selbstverständlich gibt es Ausnahmen) resultiert der Versuch, diese Kompatibilität zu erreichen, in besserem Stil.

    mag ja sein, dass manche versuchen ihren C-code C++ kompatibel zu schreiben, aber ein vernünftiger grund dazu will mir einfach nicht einfallen. die unterschiede beider sprachen sind einfach zu gross, so dass man vielleicht ca. alle 10 zeilen #ifdef __cplusplus schreiben müsste. also ne, dass muss ich mir nicht geben. hast du jemals versucht eine mittelgrosse menge C-code durch einen C++ compiler zu scheuchen oder umgekehrt?
    zur 'stilverbesserung': ich habe schon oft gesehen, was dabei rauskommt, wenn gestandene C++ programmierer C-code schreiben müssen. es ist einfach nur umständlich, resourcesfressend, grauenhaft, etc. jeder assembler- pascal- oder verilog-coder kann nach einer woche übung besseren C-code schreiben, als ein durch C++ verseuchter mensch es in einem jahr hinbekommen würde.
    🙂



  • @*-freak: Ist ja gut, pale!

    greetz, Swordfish


Anmelden zum Antworten