"Tipps" für optimales C???



  • Hallo!!!

    Hier liest man immer mal wieder so C-Tipps, wo man nie selbst drauf gekommen wäre. z.B. die Sache vorn paar Tagen, dass man den return von malloc nicht casten sollte, etc.

    Gibt es vielleicht irgendwo im Inet eine Zusammenfassung solcher Tipps???

    Also ich will keine Anfänger-Doku... C kann ich eigentlich ganz gut.. Nur die Feinheiten fehlen halt noch 😉



  • Hi,

    ich kann dir zwar keinen Link geben, aber die Tatsache, dass man in C den return
    Type von malloc nicht castet, steht in jedem C Buch.

    mfg
    v R



  • virtuell Realisticer schrieb:

    Hi,

    ich kann dir zwar keinen Link geben, aber die Tatsache, dass man in C den return
    Type von malloc nicht castet, steht in jedem C Buch.

    mfg
    v R

    jep, ich nenne da mal Programmieren in C
    von Kernighan und Ritchie 2 Ausgabe

    die wohl doch etwas konträr zu deiner Aussage steht, denn
    dort wird jedes malloc gecastet

    Witzig finde ich solche Aussprüche der Compiler wäre schlauer und kennt C besser als ich,
    !sicher sogar!, nur weiss der Compiler was ich will?



  • Ist K&R denn Standard-C? Eher nicht ...



  • dEUs schrieb:

    Ist K&R denn Standard-C? Eher nicht ...

    Nun da verweise ich auf das Vorwort zur ersten Ausgabe...
    und den Anhang C

    Wichtig für jeden Programmierer dürfte wohl eher sein, wie komme
    ich zurecht. Die stereotype Aussage malloc castet man nicht, ist
    letztendlich eine Designfrage der eigenen Programme!

    Es gilt abzuschätzen, ob ich nach einem drüberlesen über meine
    eigenen Programme nach einiger Zeit noch genau weiss, was ich da meinte.

    Darauf zielt meine Aussage. "Weiss der Compiler was ich will?"

    Er weiss, was er will! (...und die kribblige Frage, 🙄 fängt er auch alles ab...)

    Das muss nicht unbedigt das gleiche sein!



  • godwin schrieb:

    Die stereotype Aussage malloc castet man nicht, ist
    letztendlich eine Designfrage der eigenen Programme!

    Eine Designfrage vielleicht dann, wenn man (wie in de.comp.lang.c FAQ genannt) später vorhat, das Programm nach C++ umzuschreiben.

    FAQ von comp.lang.c
    http://www.eskimo.com/~scs/C-faq/q7.7.html

    Before ANSI/ISO Standard C introduced the void * generic pointer type, these casts were typically required to silence warnings (and perhaps induce conversions) when assigning between incompatible pointer types. (Under ANSI/ISO Standard C, these casts are no longer necessary.)

    References: H&S Sec. 16.1 pp. 386-7

    [H&S] Samuel P. Harbison and Guy L. Steele, Jr., C: A Reference Manual, Fourth Edition, Prentice-Hall, 1995, ISBN 0-13-326224-3.

    FAQ von de.comp.lang.c
    http://www-info2.informatik.uni-wuerzburg.de/dclc-faq/kap3.html

    Frage 3.5: Warum benutzen manche Programme ausdrückliche Typkonversionen, um den Rückgabewert von malloc() in eine Zeiger des Typs zu verwandeln, für den Speicher alloziert wurde?

    Antwort: Bevor der ANSI/ISO Standard für C den Zeiger-Typ void * einführte, brauchte man solche Konversionen, damit der Compiler keine Warnungen über inkompatible Zeiger-Typen produzierte. (Mit ANSI/ISO C sind die Konversionen nicht mehr nötig.)

    Hinweis von Uz:
    Eine explizite Konversion kann auch dann sinnvoll sein, wenn das Modul mit moeglichst wenig Änderungen in einem C++ Projekt benutzt oder später als C++ Code übersetzt werden soll. C++ konvertiert void* Zeiger nicht automatisch in typisierte Zeiger, d.h. ein Aufruf von malloc() ohne Cast des Rückgabewertes in einen typisierten Zeiger erzeugt bei der Übersetzung mit einem C++ Compiler einen Fehler. Wie wichtig dieser Grund ist muß im Einzelfall entschieden werden, es gibt auch Argumente, die gegen eine explizite Konvertierung sprechen.



  • godwin schrieb:

    dEUs schrieb:

    Ist K&R denn Standard-C? Eher nicht ...

    Nun da verweise ich auf das Vorwort zur ersten Ausgabe...
    und den Anhang C

    Wichtig für jeden Programmierer dürfte wohl eher sein, wie komme
    ich zurecht. Die stereotype Aussage malloc castet man nicht, ist
    letztendlich eine Designfrage der eigenen Programme!

    Es gilt abzuschätzen, ob ich nach einem drüberlesen über meine
    eigenen Programme nach einiger Zeit noch genau weiss, was ich da meinte.

    Darauf zielt meine Aussage. "Weiss der Compiler was ich will?"

    Er weiss, was er will! (...und die kribblige Frage, 🙄 fängt er auch alles ab...)

    Das muss nicht unbedigt das gleiche sein!

    Ich weiss aber, von welchem Typ meine Variablen sind, schlisslich sind diese am Blockanfang
    definiert und ich kann jeder Zeit dort nachschauen.

    Die Aussage "Weiss der Compiler was ich will?" lass ich nicht gelten, denn der Compiler ist
    ein Werkzeug der deinen Code uebersetzen soll. Er kann und _soll_ nicht wissen was du meinst,
    sondern lediglich deinen Code uebersetzen.

    Wenn du a und b addierst, dann hat der Compiler nicht a und c zu addieren und dass tut er
    auch nicht. Er tut das was du sagst und wenn dein Programm syntaktisch und logisch korrekt
    ist wird es auch korrekt funktionieren.

    Wenn ich wirklich vor habe das Programm spaeter in C++ umzuschreiben, muss der Cast
    natuerlich dort hin. Wir reden hier aber vom optimieren von 'C' Code und ich gehe jetzt
    einfach mal nicht davon aus, dass davon ausgegangen wird das Programm irgendwann umzuschreiben

    Nebenbei spart man sich ja auch Tipparbeit 😉 und dass alleine ist doch schon viel Wert 😃

    mfg
    v R



  • godwin schrieb:

    virtuell Realisticer schrieb:

    Hi,

    ich kann dir zwar keinen Link geben, aber die Tatsache, dass man in C den return
    Type von malloc nicht castet, steht in jedem C Buch.

    mfg
    v R

    jep, ich nenne da mal Programmieren in C
    von Kernighan und Ritchie 2 Ausgabe

    die wohl doch etwas konträr zu deiner Aussage steht, denn
    dort wird jedes malloc gecastet

    Dir ist aber schon aufgefallen, *WANN* das K&R Buch erschienen ist?
    In der ersten Auflage wurde sogar noch K&R-C programmiert.

    #include <stdio.h>
    
    main(argc, argv)
    int argc;
    char** argv;
    {
      printf("Hello World\n");
      return 0;
    }
    

    Erst in einer späteren Auflage wurde die Parameter-Syntax an ANSI-C angepasst -- die anderen Unterschiede zwischen K&R-C und ANSI-C wurden allerdings im Buch belassen und nicht bereinigt.

    #include <stdio.h>
    
    int main(int argc, char** argv)
    {
      printf("Hello World\n");
      return 0;
    }
    

    Von daher ist es nicht so passend, das malloc()-cast-Verhalten des K&R als Referenz heranzuziehen. Als K&R ihr C Buch geschrieben haben, war es halt noch notwendig den Rückgabewert von malloc() zu casten. Seit ANSI-C ist es nicht mehr notwendig und sogar besser, den Rückgabewert nicht zu casten damit Fehler im Quellcode schneller entdeckt werden.

    Meistens sieht man zum Beispiel Programme, wo der für malloc() benötigte Header nicht inkludiert wurde und dann malloc() gecastet wurde damit der Kompiler seine Klappe hält.

    Ansonsten verweise ich auf:

    Before ANSI/ISO Standard C introduced the void * generic pointer type, these casts were typically required to silence warnings (and perhaps induce conversions) when assigning between incompatible pointer types. (Under ANSI/ISO Standard C, these casts are no longer necessary.)

    References: H&S Sec. 16.1 pp. 386-7

    [H&S] Samuel P. Harbison and Guy L. Steele, Jr., C: A Reference Manual, Fourth Edition, Prentice-Hall, 1995, ISBN 0-13-326224-3.

    Also BEFORE ANSI/ISO Standard C ... das war lange her.

    Und da wir hier im ANSI C Forum sind, ist es doch nur richtig, wenn man andere Poster auf unnötige Programmierkonstrukte hinweist.



  • Ist es richtig das es nicht schadet wenn man in C auf den Typen castet den man haben will?
    Wenn das so ist, sollte es jeder nach seinem Geschmack tun, sofern er die zugehörige Headerdatei includiert.

    Frage 3.5: Warum benutzen manche Programme ausdrückliche Typkonversionen, um den Rückgabewert von malloc() in eine Zeiger des Typs zu verwandeln, für den Speicher alloziert wurde?

    Before ANSI/ISO Standard C introduced the void * generic pointer type, these casts were typically required to silence warnings (and perhaps induce conversions) when assigning between incompatible pointer types. (Under ANSI/ISO Standard C, these casts are no longer necessary.)

    References: H&S Sec. 16.1 pp. 386-7

    [H&S] Samuel P. Harbison and Guy L. Steele, Jr., C: A Reference Manual, Fourth Edition, Prentice-Hall, 1995, ISBN 0-13-326224-3.

    Wenn ich den Text hier richtig interpretiere steht hier "Mit ANSI/ISO C sind die Konversionen nicht mehr nötig"
    und nicht verboten, oder nicht mehr anzuwendenm, oder depreciated oder ähnliches.

    ➡ Und noch eine ketzerische Frage, warum besteht den C++ darauf das man explicit castet??
    Wahrescheinlich das man sich Gedanken macht was man an der Stelle haben möchte.

    🕶 oder hat da C++ eine Nachteil gegenüber C?. 🕶

    Und da wir hier im ANSI C Forum sind, ist es doch nur richtig, wenn man andere Poster auf unnötige Programmierkonstrukte hinweist.

    "Mit ANSI/ISO C sind die Konversionen nicht mehr nötig"

    bedeuted etwas ganz anders als der Text "man soll nicht casten".

    Da es also weder verboten noch schädlich ist, sollte man auch nicht darauf herumreiten das man es nicht tut.



  • Gibt es vielleicht irgendwo im Inet eine Zusammenfassung solcher Tipps???

    lies dir regelmäßig Beiträge in dem Forum durch. Besonders wenn in den Threads Shade, Daniel E., Bashar oder Descartes posten, findet man oft ein paar interessante Dinge. Dann steht auch viel in den verschiedenen FAQs.

    @PAD
    ich glaub im Struppi, den du ja immer zitierst, steht warum Bjarne kein implizites casten von void* zu typisierten Pointern haben wollte.

    Ansonsten ist das ja auch nicht wirklich weiter schlimm, da man bei C++ ja eh kein malloc verwenden sollte. Wozu haben wir denn new?



  • Man könnte auch einfach 2 bis 3 Wochen de.comp.lang.c lesen. (Danach abbestellen nicht vergessen)



  • Folgendes Usenet Posting finde ich hierzu ganz passend:

    From: "Richard Heathfield" complangc@eton.powernet.co.uk
    Subject: Re: Why not cast malloc?
    Message-ID: 01bf7633$364d2ba0$0e01a8c0@arc5.croydon#1/1
    Newsgroups: comp.lang.c

    Andrew Jones luminous-is@home.com wrote in article
    tkzp4.38012$45.2077485@news2.rdc1.on.home.com...
    > I've read in a few threads here people saying that you shouldn't cast malloc's
    > return in C. Why is this? I almost always cast, and never had a problem. I
    > find it makes it easier for me to remember just what it was I was allocating
    > memory for.

    We write code either because it has a positive benefit or because it
    prevents something bad happening.

    In C, casting doesn't prevent anything bad happening. For char *p,

    p = malloc(1000);

    and

    p = (char *)malloc(1000);

    are equivalent - the cast doesn't do anything wonderful that we need in
    order to be able to use the memory. So it has no positive benefit, and it
    doesn't prevent anything bad happening. So why put it in?

    Now consider what happens if you have unaccountably forgotten to #include
    <stdlib.h>.

    The line

    p = malloc(1000);

    will give you a diagnostic, because the compiler will have assumed, in the
    absence of any other information, that malloc returns int, but here you are
    trying to assign it as if it were a pointer.

    The line

    p = (char *)malloc(1000);

    may well /not/ give you a diagnostic. The cast assures the compiler that
    all is well. You are, effectively, saying to the compiler "yes I know
    malloc returns int, but - for reasons which make perfect sense to me but
    which it's impossible to explain to you - I want to pretend it's a char *.
    I know exactly what I'm doing, so trust me, it'll be fine".

    The compiler is now free to generate code on the assumption that malloc
    returns int. Consider a system where sizeof(void 😉 == 8 but sizeof(int) ==
    2. The compiler may store the result of the malloc call in a 16-bit
    register rather than a 64-bit register. The consequences to your code could
    be unfortunate.

    In this case, then, casting gives you no benefits, prevents no problems,
    gives you /more typing/ to do, and potentially conceals a serious bug. So
    why do it?

    > Anyone care to elaborate on why it seems to be such a no-no? (Or is it in the
    > FAQ?) 🙂

    I trust this answer is elaborate enough for you. If not, let me know - I
    have some oak veneer somewhere... 😉



  • @kingruedi

    Deswagen muss man ja in C++ explicit casten.
    Wenn es da gut ist warum ist es dann in C schlecht.

    @Descartes Das Posting ist interessant und plausibel und das Argument ist gut bis sehr gut

    Now consider what happens if you have unaccountably forgotten to #include <stdlib.h>.

    Wenn ich auf oder für unterschiedliche Platformen programmiere ist es eigentlich das Argument nicht zu casten.

    Für alle anderen Fälle, Dappigkeit (vergessen <stdlib.h>) gegen Lesbarkeit (cast) sollte jeder selber gegeneinander abwägen.



  • PAD schrieb:

    Deswagen muss man ja in C++ explicit casten.
    Wenn es da gut ist warum ist es dann in C schlecht.

    Eigentlich sind void-Zeiger in C++ immer 'schlecht'.

    In C++ wird dem Programmierer aufgetragen, den korrekten Typ des void-Zeigers (worauf er eigentlich zeigt) zu kennen. Es ist ja zB so, dass Zeiger auf Integer nur auf Adressen die restlos durch sizeof(int) teilbar sind liegen können. Wenn der originale void* auf eine Adresse zeigt, die nicht von int* referenziert werden kann, so hat der Code UB, in C wie in C++. Ob dieser Unterschied in der Praxis irgendeine Relevanz hat ist natürlich die andere Frage: Tritt so ein Fehler auf (also ein void* kann nicht implizit in Typ* umgewandelt werden), so wird nach meiner Erfahrung nach einfach geschaut, welcher Typ links steht und dann wird gecastet. Naja, wenigstens kann sich C++ angeblich, dank dieser Änderung, getrost 'typensicher' nennen.



  • Daniel E. schrieb:

    Es ist ja zB so, dass Zeiger auf Integer nur auf Adressen die restlos durch sizeof(int) teilbar sind liegen können.

    Du meinst, das könnte so sein.



  • Hallo ersteinmal!

    Ich habe mal gelesen, da mitlerweile sehr viele Leute Ihren C- Quelltext nicht immer mit einen reinen C-Compiler compilieren (sondern mit einen C/C++ Compiler), sollte man sich besser angewöhnen das malloc zu casten. C kommt auf jeden Fall auch ohne casten aus im Gegensatz zu C++.

    Gruß

    JoeF



  • JoeF schrieb:

    Ich habe mal gelesen,

    Irrelevant

    JoeF schrieb:

    Da mitlerweile sehr viele Leute Ihren C- Quelltext nicht immer mit einem reinen C-Compiler compilieren (sondern mit einen C/C++ Compiler),

    Dann benutzen halt "sehr viele Leute" ihre Werkzeuge halt ganz einfach falsch.
    Wer nur einen Hammer hat, behandelt jedes Problem wie einen Nagel.

    JoeF schrieb:

    [Daher] sollte man sich besser angewöhnen das malloc zu casten. C kommt auf jeden Fall auch ohne casten aus im Gegensatz zu C++.

    Aha. Sehr interessante Meinung.

    Ich fasse mal zusammen, was du uns sagen möchtest:

    Da mittlerweile sehr viele Leute ihre Schrauben mit einem Hammer einschlagen, statt sich mehrere Werkzuge zu bedienen, sollte man sich besser angewöhnen, Schrauben mit dem Hammer einzuschlagen. Schrauben kann man aber auch mit einem Schraubendreher eindrehen, im Gegensatz zu Nägeln.



  • Bashar schrieb:

    Daniel E. schrieb:

    Es ist ja zB so, dass Zeiger auf Integer nur auf Adressen die restlos durch sizeof(int) teilbar sind liegen können.

    Du meinst, das könnte so sein.

    Nein, wenn ich mir den Satz nochmal durchlese muss ich feststellen, absoluten Blödsinn geschrieben zu haben (ohne Kommafehler): Ich meinte selbstverständlich nicht 'liegen' sondern 'zeigen'. Und auch sonst sollte ich natürlich deutlicher unterstreichen, dass das nicht immer so sein muss, sondern nur ein frei erfundenes Beispiel war, richtig.



  • Schön das es auch hier immer Neu-mal-kluge Leute gibt.

    Descartes schrieb:

    Aha. Sehr interessante Meinung.

    Ich fasse mal zusammen, was du uns sagen möchtest:

    Da mittlerweile sehr viele Leute ihre Schrauben mit einem Hammer einschlagen, statt sich mehrere Werkzuge zu bedienen, sollte man sich besser angewöhnen, Schrauben mit dem Hammer einzuschlagen. Schrauben kann man aber auch mit einem Schraubendreher eindrehen, im Gegensatz zu Nägeln.

    Schön das du weißt was ich euch sagen möchte: , irgendwie war von Hammer und Nägeln nie die Rede.

    Ich habe ja nicht behauptet, dass es so gut ist.
    Also nochmal: Wenn Autoren ein Buch schreiben, schreiben sie es oftmals für die breite Masse (also auch für Anfänger) und da C und C++ eng miteinander verwandt sind wollen sie (denke ich zumindestens) speziell den Anfänger nicht durcheinander bringen. Und du wirst mir wohl recht geben, dass die meisten nicht einen reinen C- Compiler benutzen (ich weiß du ja).
    Um nun also Fehler vorzubeugen, mußt man malloc casten.

    Nohmal es sollte ja garkein Aufruf werden, absofort nur noch C++ Compiler zu benutzen, um ein C-Quellcode zu kompilieren, sondern nur der Versuch einer Erklärung warum so oft die Diskussion aufkommt wegen dem malloc und casten oder nicht.

    Gruß

    JoeF



  • wenn man denn mal malloc, calloc benutzt bleibt einem ja wohl ichts anderes übrig.

    Das nutzen dieser verpönten funktionen ist immer dann interessant wenn man funktionierende Routinen oder
    Libraries aus C in C++ weiterverwendet, man muß man im ersten Schritt "nur" die casts nachrüsten. Später wenn man Zeit und Geld in dem Projekt hat, kann man dann übere bessere Portierungen nachdenken



  • JoeF schrieb:

    Schön das es auch hier immer Neu-mal-kluge Leute gibt.

    Das nimmst du sofort zurück 😉

    JoeF schrieb:

    Ich habe ja nicht behauptet, dass es so gut ist.

    Dann sind wir ja einer Meinung.

    JoeF schrieb:

    Also nochmal: Wenn Autoren ein Buch schreiben, schreiben sie es oftmals für die breite Masse (also auch für Anfänger)

    Hmmm. In Büchern für "die breite Masse" steht auch manchmal der grösste Scheiss. Da findet man dann Bücher wo z.B. "void main" drinsteht oder (bei C++) #include<iostream.h> oder es wird ohne "std::" und ohne "using namespace std;" direkt string verwendet.

    Es gibt natürlich auch andere, bessere Bücher die diese Fehler nicht enthalten wo der Autor aber trotzdem z.B. malloc() grundlos castet. Ganz einfach daher, weil er es selber nicht besser wusste.

    JoeF schrieb:

    und da C und C++ eng miteinander verwandt sind

    Sie entstammen der gleichen Quelle und teilen Syntax und Semantik. Aber das trifft auch auf die Verwandschaftsbeziehung zwischen C und Objective-C, Pike oder Cilk zu.

    Man kann zwar noch C Quellcode mit einem C++ Compiler kompilieren, aber damit hat es sich auch schon.

    JoeF schrieb:

    wollen sie (denke ich zumindestens) speziell den Anfänger nicht durcheinander bringen.

    Gerade Anfänger sollte man darauf hinweisen, dass ein malloc()-cast nicht notwendig ist. Und die wenigen Spezialfälle, wo man malloc() doch mal casten muss, sind für Anfänger erst einmal uninteressant.

    JoeF schrieb:

    Und du wirst mir wohl recht geben, dass die meisten nicht einen reinen C- Compiler benutzen (ich weiß du ja).

    Stimmt. Wenn ich gcc benutze (nicht verwechseln mit g++), verwende ich einen reinen C Compiler.

    Und um C++ Quellcode ging es ja nicht. Desweiteren verwendet man in C++ Programmen nicht malloc()/free() sondern new/delete und muss deswegen auch nicht casten 🙂 Und wenn doch, dann verwendet man dynamic_cast<T>(var), static_cast<T>(var) oder reinterpret_cast<T>(var).

    JoeF schrieb:

    Um nun also Fehler vorzubeugen, mußt man malloc casten.

    ...nur, wenn man innerhalb C++ ist. Dann musst du malloc() casten. Aber wir sind hier im ANSI C Forum, weswegen ich ausschliesse dass der Fragesteller C++ verwendet.

    JoeF schrieb:

    Nohmal es sollte ja gar kein Aufruf werden, ab sofort nur noch C++ Compiler zu benutzen, um ein C-Quellcode zu kompilieren, sondern nur der Versuch einer Erklärung warum so oft die Diskussion aufkommt wegen dem malloc() und casten oder nicht.

    ...also nicht casten, ausser man programmiert innerhalb eines C++ Programmes mit C.


Anmelden zum Antworten