Ergebnis 1 bis 20 von 20

Thema: Fallstricke des Programmierens - Beispiele

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1

    Fallstricke des Programmierens - Beispiele

    Dieser Thread ist fuer alle Fallstricke des Programmierens gedacht.
    Wenn ihr etwas interessantes findet, oder selber etwas verbrochen habt, was euch kurios oder wichtig vorkommt, immer her damit.

    @ Magor unter mir: Ich habe mal deinen Thread gekapert und entfremdet, da das Problem ja geloest war Ausserdem war dein Beispiel ein toller Einstieg zum Thema.

    Geändert von Ineluki (02.09.2009 um 14:28 Uhr)

  2. #2
    Stimmt, da wäre es sinnvoll, zu meckern, genau wie bei:
    Code:
    bool a, b;
    // ...
    if (a = b)
        // ...
    (Dort meckern ja afaik auch die meisten Compiler in den meisten Sprachen.)

  3. #3
    Also ich finde das etwas überheblich. o_O Jedem kann mal ein Tipp- bzw. Schlampigkeitsfehler passieren, gerade bei solchen Sachen, und da man da echt praktisch nie das meint, was es wirklich bedeutet, könnte/sollte da imo schon eine Warnung erfolgen. Tut es zwar anscheinend weder bei C, noch Java oder PHP (entgegen meiner Vermutung), aber trotzdem wird vor allem a < b < c praktisch nie jemand wirklich so meinen (außer halt in Sprachen, wo's die klassische mathematische Bedeutung hat).

    Dass es rein theoretisch gültig ist, und was es bedeutet, wissen wir alle.

  4. #4
    Zitat Zitat
    Also ich finde das etwas überheblich. o_O Jedem kann mal ein Tipp- bzw. Schlampigkeitsfehler passieren, gerade bei solchen Sachen, und da man da echt praktisch nie das meint, was es wirklich bedeutet, könnte/sollte da imo schon eine Warnung erfolgen. Tut es zwar anscheinend weder bei C, noch Java oder PHP (entgegen meiner Vermutung),
    Gerade in PHP wird zumindest das:
    Code:
    bool a, b;
    // ...
    if (a = b)
        // ...
    sehr häufig verwendet. Ich benutze es eig. jeden Tag.

    Das bekannteste Beispiel dürfte sein:
    PHP-Code:
    while($row mysql_fetch_assoc($result)) { 
    Btw. darf man in PHP nicht: $a < $b < $c schreiben

    Geändert von Xardas der Dunkle (02.09.2009 um 22:34 Uhr)

  5. #5
    Zitat Zitat von Xardas der Dunkle Beitrag anzeigen
    Gerade in PHP wird zumindest das:
    Code:
    bool a, b;
    // ...
    if (a = b)
        // ...
    sehr häufig verwendet. Ich benutze es eig. jeden Tag.
    Natürlich, da meinte ich auch mehr das andere, bzw. andere Sprachen. ^^" Aber hätte ich das jetzt alles gut ausformuliert, wäre der Post komplett unlesbar geworden. XD
    Und in Java z.B. geht sowas ja nur bei booleans, da braucht man das wohl deutlich seltener. Aber klar, in PHP verwende ich's auch ständig.

    Nur kann ich mir echt nicht vorstellen, dass hier jemals jemand a < b < c tatsächlich so gemeint hat. PHP verbietet das netterweise sogar. ^^ Naja, und in Java geht's ja sowieso nicht…
    Dass es jemand mal unabsichtlich schreibt, kann ich mir da schon deutlich eher vorstellen, auch wenn's mir persönlich afair noch nie passiert ist.

  6. #6
    Gerade C legt großen Wert darauf, dem Programmierer so viel Freiraum zu lassen, wie es möglich ist. Wie Ineluki schon schrieb, ist das Motto von C: Der Programmierer weiß was er tut. Das hat Nachteile, ganz klar, so wie beispielsweise in Inelukis Fall, aber auch enorme Vorteile in der Performance und Freiheit, Punkte, die für eine Systemsprache essentiell sind. (Das heißt natürlich nicht, dass C das Non plus ultra ist und es nicht mehr besser geht, aber im Moment reden wir von C und an dieser Sprache wird sich kaum etwas so schnell ändern.)
    Um zu verstehen, weshalb ich es nicht für sinnvoll halte, bei einer Verkettung wie 'a < b < c' eine Warnung zu generieren, musst du verstehen was ein Ausdruck in C ist, wie der Compiler Verkettungen auflöst, wozu implizite Konvertierung da ist, welcher Typ als Resultat einer Vergleichsoperation zurückgegeben wird, grundsätzlich alles über Typen in C, ihre Wertebereiche und wie zwischen verschiedenen Typen konvertiert wird, usw. In C gibt es keinen built-in Boolean-Typ. Bei einer Vergleichsoperation wird 0 oder 1 zurückgegeben, als int-Wert, so dass ein erneuter Vergleich mit dem zurückgegebenen Wert semantisch absolut Sinn macht, solange nicht mit einem Typ vergleichen wird, dessen Wertebereich kleiner ist, als der eines int.
    Dazu kommt noch, dass man mit einer Warnung, die 'a < b < c' in Frage stellt, noch lange nicht fertig ist mit Verkettungen von Ausdrücken in C, die zwar syntaktisch und semantisch korrekt sind, aber nicht das widerspiegeln könnten, was der (unerfahrene) Programmierer gemeint haben könnte, dazu lässt C einfach zu viel Freiraum zu, und zu versuchen alles abzudecken ist schier unmöglich. Es ist Cs Charakter, wenig Regeln aufzustellen und den Programmierer machen zu lassen, wozu er Lust hat, solange es syntaktisch und semantisch valide ist und du ahnst gar nicht wie kreativ dabei manche Programmierer werden können, auch außerhalb des Obfuscated C Code Contests. Wenn man Cs Tücken ohne jahrelanger Praxis effektiv vermeiden will, sollte man C einfach nicht benutzen und zu einer Sprache wechseln, die strikter ist.

  7. #7
    Zitat Zitat von Kyuu Beitrag anzeigen
    Um zu verstehen, weshalb ich es nicht für sinnvoll halte, bei einer Verkettung wie 'a < b < c' eine Warnung zu generieren, musst du verstehen…
    Ja, danke, das verstehe ich natürlich alles. Ich kann C, und bin mir auch, wie bereits geschrieben, darüber bewusst, dass der Ausdruck theoretisch komplett korrekt ist.
    Ich bin mir nur bei diesem speziellen sicher, dass der praktisch nie sinnvoll angewendet werden kann. Und da wäre, bei -Wall, mMn eine Warnung vertretbar, "Sorry, stimmt eigentlich eh, aber wolltest du das wirklich?".
    Luki ist sicher kein Anfänger, und wenn selbst ihm das mal passiert ist (anscheinend vor ziemlich kurzem), kann das auch anderen guten Programmierern passieren. Und warum dann nicht davor warnen, wenn das bei anderen Sachen, die Absicht sein könnten, ohnehin schon gemacht wird?

    Aber ist natürlich nur meine Meinung.

  8. #8
    Ich stimme Saeuferaeffchen voll zu. Ich habe schon fast ein Jahrzehnt Programmiererfahrung in C und etwa 2 Jahrzehnte Programmiererfahrung insgesammt.

    Trotzdem kann einem soetwas schnell passieren, insbesondere, wenn man mathematische Formeln/Algorithmen uebertraegt. Dass C nicht erkennt, was ein bool ist, und was ein int ist, nicht zwingend so. Es ist zwar nicht als eigener Datentyp spezifiziert, aber der Compiler hat alle Informationen, das zu entscheiden, und gerade hier WEISS der compiler, sogar, dass a<b ein bool ist, und es waehre ein Leichtes fuer ihn, es von einem int zu unterscheiden. Und wann testet man ein bool schon mal auf < oder > ? Auf bools operiert man mit == true, !, || und &&, normalerweise vergleicht man sich nicht mit < oder >, denn das entspricht nicht ihrer Natur. Und das weiss auch der Compiler, weswegen er einen indirect cast von bool nach double macht, um < anwenden zu koennen.

    In meinen Augen ist eine automatische Konvertierung von bool nach double zwar haeufig sinnvoll, jedoch in vielen Faellen eben nicht. Wenn ich unsigned int mit int vergleiche, warnt mich doch -Wall auch, und sei es nur, dass ich in meiner for-schleife den datentyp size_t verwende, und dann mit einem anderen berechneten Index von typ int vergleiche, auch wenn ich als Programmierer weiss, dass der Index sich im Bereich 0 bis ca. 100 bewegen wird.

    -Wall gibt schon SEHR viele Warnungen aus. Da wuerde diese eine mehr wirklich nicht schaden. Ausserdem heisst eine Warnung ja nich, dass man was falsch gemacht hat, sondern dass man moeglicherweise etwas getan hat, was man so nicht wollte. Und wenn man unbedingt mit a<b<c etwas anderes meint, kann man auch explizit ein ((double)a<b)<c schreiben. Dann weiss naemlich nicht nur der compiler, was abgeht, sondern auch der Programmiere beim ueberfliegen des Quellcodes. Ein Konstrukt wie a<b<c interpretiert man beim schnellen(!) Codescreening eben NICHT als das, was es eigentlich meint.

    Und mal ehrlich: Was ist Ziel des ganzen ? Eine Sprache, die jede Syntax unkommentiert uebernimmt (dann benutze einfach nicht -Wall) oder eine, die auch mal nachfragt, ob man das auch wirklich so meint. Es ist ohnehin sauberer, d.h. verstaendlicherer Code, wenn man in diesem Fall ausschreibt, dass man ein bool mit einem double vergleichen will.

  9. #9
    Ich stimme Luki in allen Punkten zu. Allerdings ist mir tatsächlich eine sinnvolle (aber nicht wirklich schöne) Verwendung für < und > bei bools eingefallen.

    Code (C):
    bool a, b;
    // ...
    if(a < b)

    ist eine kürzere Schreibweise für
    Code (C):
    bool a, b;
    // ...
    if(!a && b)


    Im Übrigen kennt C soweit ich weiß, sehr wohl bool, wenn auch erst seit ANSI C99.

  10. #10
    C99 kennt _Bool, das ändert aber nichts daran, dass der Standard den Rückgabetyp der Vergleichs- und Logikoperatoren als int definiert:

    Zitat Zitat von http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
    Each of the operators < (less than), > (greater than), <= (less than or equal to), and >=
    (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.92)
    The result has type int.

    [...]

    The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
    yields 0. The result has type int.

    [...]

    The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
    yields 0. The result has type int.
    Ich weiß jetzt nicht die genauen Implementationsdetails eines Compilers, aber in diesem Fall erfordert eine Verifikation, ob das Ergebnis des als letztes ausgewerteten Ausdrucks ein Boolescher Wert war, oder nicht, zusätzlichen Aufwand, da der Compiler mehr wissen muss, als zuvor. _Bool ist übrigens kein int.

    Ansonsten:

    Zitat Zitat von http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
    The expression a<b<c is not interpreted as in ordinary mathematics. As the syntax indicates, it
    means (a<b)<c; in other words, ‘‘if a is less than b, compare 1 to c; otherwise, compare 0 to c’’.
    Wenn sogar die Spezifikation diesen Umstand erwähnt, werden ihn die Entwickler mit Sicherheit bedacht haben. Das Beispiel klingt nicht nur logisch, sondern ist auch definitiv nützlich. Es ist ja nicht so, als wären es Idioten und in all den Jahrzehnten von C, hätte es keine Kritik diesbezüglich gegeben.

    Geändert von Kyuu (03.09.2009 um 15:25 Uhr)

  11. #11
    Kyuu es geht doch gar nicht darum, dass jemand nicht verstanden hat, was a<b<c tut. Ich denke, das weiß in der Zwischenzeit jeder hier und versteht auch jeder, der sich den Code genauer anschaut.

    Es geht darum, dass Warnings den Programmierer darauf hinweisen (sollten) wenn er etwas tut, was zwar syntaktisch richtig, aber in den allermeisten Fällen semantisch nicht das gewollte ist und da stimme ich zu, dass zumindest mit -Wall darauf hingewiesen werden sollte, dass a<b<c kein guter Stil da auf den ersten Blick missverständlich ist. Im Stil von a<b<c might not be what you wanted. Did you mean a<b && b<c?. Das machen manche Compiler zum Beispiel auch bei if(a = b) und da halte ich es für wesentlich weniger notwendig, weil man das tatsächlich in vielen Fällen so meint. Aber auch da wäre es unter Umständen schöner verständlicher, if((a = b) != 0) bzw. if((a = b) == TRUE) zu schreiben.

  12. #12
    Ich weiß nicht, wie du darauf kommst, ich würde in dem Post die Funktionsweise von 'a < b < c' erklären...? Der erste Teil war zum Teil an dich gerichtet (bezüglich "Im Übrigen kennt C soweit ich weiß, sehr wohl bool, wenn auch erst seit ANSI C99") und zum Teil an Ineluki, der zuvor annahm, dass der Compiler mit booleans arbeiten würde. Tut er nicht, wie man dem Standard entnehmen kann. In C sind Rückgabetypen von Vergleichs- und Logikoperatoren keine bools und keine _Bools, sondern ints (!= bool/_Bool). Dieser Fakt wiederum erschwert die semantische Verifikation, ob einer der Operanden vom Typ bool/_Bool ist, oder nicht, und damit ist es auch nicht so trivial (entgegen Inelukis Annahme) eine Warnung oder Fehler zu generieren, wenn implizit von einem bool/_Bool konvertiert wird, da eben keine bools/_Bools in den Ausdrücken entstehen.
    Der letzte Teil sollte nur noch zeigen, dass 'a < b < c' sogar im Standard erwähnt wird, da offenbar ausreichend beanstandet wurde, und dennoch gibt es bis heute keine generierte Warnung auf der Seite der Implementation, folglich als nicht kritisch genug erachtet. Und genau das ist auch meine Ansicht, siehe mein erster Kommentar diesbezüglich. Ob 'a < b < c' im mathematischen Sinn gemeint war, kann man sofort aus dem Kontext erkennen und wie gesagt, meiner Meinung nach würde so ein Fehler einem erfahrenen Programmierer nicht unterkommen. Spätestens sobald der obligatorische Test fehlschlägt, sollte man beim Überfliegen diesen Fehler entdecken.
    Ich hoffe, ich habe es diesmal besser ausgedrückt. Eure Ansichten sind mir nicht egal, und ich versuche auch nicht euch meine Meinung aufzubinden (falls dies den Anschein erwecken sollte, ich bin in Diskussionen oft ehrgeizig), ich sehe es nur anders als ihr und habe versucht meinen Standpunkt wiederzugeben.

    Edit: Zugegeben, in der syntaktischen Analyse könnte eine Warnung viel einfacher generiert werden, da es bei 'a < b < c' in erster Linie nicht um die Semantik geht, sondern dass diese Syntax nicht mathematisch korrekt aufgelöst wird.

    Geändert von Kyuu (03.09.2009 um 16:48 Uhr)

  13. #13

    +=

    Neulich in PHP passiert; Das sind immer Bugs, nach denen man lange suchen muss. Die Syntaxart ist C folgend zwar korrekt, aber verwirrend.

    PHP-Code:
    $maxSpeps 60//maximum repetitions
    $allSteps 0//set the start value to 0
    $oneStep 2//number which will ne added to $maxSpeps at every repition

    while ($allSteps <= $maxSpeps) {

         
    // actions

         
    $allSteps += $oneStep;

    Die Schleife im Beispiel-Skript soll so oft durchlaufen werden, bis $allSteps = $maxSteps ist. $allSteps wird dabei in jedem Schritt um $oneStep erhöht.
    Das Problem liegt hier in der vorletzten Zeile. Die Erhöhung von $allSteps wird per += durchgeführt. Wenn die zwei Zeichen umdreht und versehentlich =+ schreibt, schlägt das ganze fehl.

    Für mich erschien es logisch, zuerst (=) die Zahl zu nehmen, und dann die folgende hinzuzufügen (+). Tja, pech gehabt!

  14. #14
    Ich kann dir sogar den Grund dafür sagen. Stell dir das Ganze mal mit - statt + vor. Dann wäre für den Compiler im Fall a=-b kein Unterschied zwischen a =- b und a = -b erkennbar.

  15. #15
    Ganz abgesehen davon wird die Schleife nicht durchlaufen, bis $allSteps == $maxSteps, sondern bis $allSteps > $maxSteps. *klugscheiß*

    Aber sonst, ja, kann mir vorstellen, dass man so einen Fehler auch nicht gleich sieht, wenn man ihn mal macht. ^^"

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •