Archiv für die Kategorie ‘C / C++’

Solange Du Deine Füße unter meinen Tisch stellst…

Montag, 06. Juli 2009

…bzw. solange Du Dich von mir ableitest, machst Du was ich sage!

Ich finde, dies ist mal wieder ein wunderschönes Beispiel dafür, wie Objektorientierung nicht funktioniert! Gefunden von meinem Kollegen in freier Wildbahn (Namen wurden von der Redaktion geändert :) )

Image-37

C driven C#

Mittwoch, 24. September 2008

Alte Gewohnheiten wird man oft nicht los, auch wenn es längst keinen Grund mehr gibt daran festzuhalten. So habe ich z.B. folgendes Konstrukt in unserem C#-Code gefunden, welches offensichtlich von einem eingefleischten C++ Programmierer kommt:

ClassA a = new ClassA();
if( a != null )
{
   …
}

Was in C++ noch Richtig war, ist in C# in dieser Art und Weise einfach Unsinn. In C++ konnte es natürlich passieren, wenn es keinen Speicher mehr gab, das der new-Operator als Ergebnis “NULL” lieferte. In C# jedoch wird in diesem Fall eine Exception “geschmissen”. Genauer gesagt die OutOfMemoryException. Was leicht in der MSDN nachgelesen werden kann. Sollte einem C/C++ Programmierer immer noch ein ungütes Gefühl beschleichen, steht einem ja ein Blick in die C#-Language-Specification offen, die ja bei Microsoft runtergeladen werden kann. Für die Sprachversion 1.2 ist im Kapitel 7.5.10.1 folgendes zu lesen:

AIf there is not enough memory available to allocate the new instance, a System.OutOfMemoryExceptionis thrown and no further steps are executed

Dort steht es also schwarz auf weiss. Sogar noch mit dem Hinweis, das keine Anweisung nach dem new Ausgeführt werden (was ja ein wesentlicher Teil des Exception-Handlings ist). Somit kann getrost auf die if-Abfrage verzichtet werden. Möchte man wirklich überprüfen ob nicht genug Speicher vorhanden war, kann man wie gewohnt mit try/catch die Exception abfangen. Über die Sinnhaftigkeit lässt sich vortrefflich streiten. Dies würde aber diesen Eintrag sprengen und muss nochmal an anderer Stelle etwas ausführlicher Diskutiert werden.

If und If gesellt sich gern

Mittwoch, 09. April 2008

Heute ist mir bei einem Code-Review wieder ein kleines Schmankerl unter die Augen gekommen.
Wie immer reduziere ich es auf das Wesentliche…

Der Aufbau war wie folgt:

if( A )
{
    a;
}
if( !A )
{
    b;
}
else
{
    c;
}

Als kleine Denksportaufgabe, könnte Ihr euch ja mal RatzFatz überlegen, wie das wohl einfacher geht… Und wenn Ihr eine Idee habt, einfach den ganzen Artikel anschauen…

(weiterlesen…)

Pseudodynamsicher l-value

Donnerstag, 29. November 2007

Ein System kann man ja nur von Innen heraus zerstören, deshalb habe ich mir überlegt wie ich zurückschlagen kann. Wenn ich die Menschen schon nicht dazu bringen kann, über ihren eigenen Code nachzudenken, so muss ich sie wenigstens dazu bringen sich über meinen Gedanken zu machen :-)

Mir ist aufgefallen, das viele Programmierer den “tertiären”-Operator ?: überhaupt nicht mögen. Ich finde richtig eingesetzt, ermöglicht er an vielen Stellen einfach schöneren und auch lesbareren Code. Aber da ja eine Aversion gegen diesen Operator zu herrschen scheint, habe ich mir ihn für die ersten Gegenschläge zum “Freund” gemacht #grins#

Folgendes kleines Konstrukt habe ich mir ausgedacht:

iTo < iLastTo ? iTo : iTi += fPrecision ? pi_i64SlaveRaster : pi_i64NetRaster;

Na was macht diese kleine Programmzeile? Ist doch nicht so schwer, oder? :-)

(weiterlesen…)

this kann doch nicht sein…

Donnerstag, 14. Juni 2007

Von einem Arbeitskollegen habe ich folgendes kleines Schmuckstück erzählt bekommen, welches ich zum besseren Verständnis einfach mal in ein kleines, kurzes und zusammenhängendes Beispiel gegossen habe:

class MeineKlasse
{
public:

void set( int x )
{
if( this == NULL ) throw new ArgumentNullException();
this.x = x;
}

private: int x;
};

Zu dieser Originalität fällt mir nichts ein, was ich darauf noch sagen könnte…

Wenn “de Morgan” leise graut…

Donnerstag, 24. Mai 2007

Heute bin ich in unserem Quellcode auf folgendes Schuckstück gestoßen:

if( x1 >= x2 || ( !( x1 < x2 || y1 < y2 ) && z1 >= z2 ) )
{
// Do other very crazy stuff
}

Als ich dies gelesen habe, hat mich sofort ein komisches Gefühl beschlichen ohne sofort zu wissen warum (Intuition?). Dann habe ich den Ausdruck mal näher untersucht.

Zuerst habe ich mal !( x1 < x2 || y1 < y2 ) aufgelöst.
Nach den Gesetzen von De Morgan ist !( A || B ) = !A && !B. Das ergibt:

!(x1<x2) && !(y1<y2)

Wenn jetzt x1<x2 bzw. y1<y2 wahr ist, so ist x1>=x2 bzw. y1>=y2 falsch. Daraus folgt:

!( x1 < x2 || y1 < y2 ) == x1 >= x2 && y1 >= y2

Dies setzen wir wieder in die gesamte Logikgleichung ein:

x1 >= x2 || ( x1 >= x2 && y1 >= y2 && z1 >= z2)

Dies entspricht dem Boolschen Ausdruck A || ( A && B && C ). Wenn A also true ist, ist perse der ganze Ausdruck wegen der Veroderung mit A true. Ist A false, so kann der ganze Ausdruck nur noch true werden, wenn A && B && C true wird. Da A in diesem Fall aber false ist, ist A && B && C auch immer false. Somit entspricht dieser Ausdruck einfach A.

Dies bedeutet, die obige if Anweisung kann auf folgende reduziert werden:

if( x1 >= x2 ) {…}

Unless – if mal anders

Montag, 21. Mai 2007

Es gibt große Firmen, bei denen etwas nur perfekt ist, wenn möglich viel Funktionalität in die Software gekloppft wird. Dies artet auch schonmal in diversen Allmachts- und Weltherschaftsgedanken aus. Ich bin jedoch der Ansicht, etwas ist erst dann perfekt wenn man bei gleichbleibener Funktion nichts mehr weglassen kann. Einige Kollegen meiner Zunft sehen dies ähnlich und bemühen sich die Code-Massen in Zaun und übersichtlich zu halten. Aus diesem Grund enstehen z.B. in diversen Programmiersprachen neue Schlüsselwörter. Eines dieser Schlüsselwörter ist in der Sprache Perl entstanden: unless

Die Funktionsweise ist schnell erklärt: unless ist eine negierte if Abfrage. Sie ist aus der Idee enstanden, das Fehlerbehandlungen in der Regel durchgeführt werden, wenn eine Aktion fehlgeschlagen ist. Mit einer if Abfrage muss dann im Normalfall die Fehlerabfrage erneut negiert werden um in den entsprechenden Anweisungsblock zu verzweigen.
Beispiel:

if( ! FileExist(”test.txt”) )
{
// Fehlerbehandlung
}

Mit Hilfe des unless Schlüsselwortes, kann dies noch ein quäntchen Schöner formuliert werden:

unless( FileExist(”Test.txt”) )
{
// Fehlerbehandlung
}

Bei dieser Formulierung kann nun nichts mehr weggelassen werden und ist somit in meinen Augen “perfekt”.

Warum komme ich darauf? Es gibt einige Zeitgenossen die sich auch für eine unless Schreibweise erwärmen können, auch wenn dieses Schlüsselwort nicht existiert. Denn folgendes Programmkonstrukt habe ich neulich entdeckt:

if( FileExist(”test.txt”) ); else
{
// Fehlerbehandlung
}

Dieses Konstrukt ist sehr unschön, da es den natürlichen “Lesefluß” unterbricht. Ist man der Meinung, dass dieses Vorgehen eine Bereicherung für die Quelltextqualität ist, so sollte man an “zentraler” Stelle eines der beiden folgenden Makros definieren:

#define unless( arg ) if( arg ); else

oder

#define unless( arg ) if( ! ( arg ) )

Es wäre auch eine gute Idee dieses Vorgehen in den Programmierrichtlinien festzuhalten. Überredet man nun noch seinen Editor unless als Schlüsselwort anzuzeigen, hat man eine ziemliche Bereicherung für einfache Fehlerfälle.

Was man aber dann tunlichst vermeiden sollte ist, einen else Zweig an seine unless Abfragen anzuhängen. In solchen Fällen ist wegen der Lesbarkeit stets eine if Abfrage zu verwenden.

&& geht sogar in if(…)

Donnerstag, 15. März 2007

Dieser Beitrag ist wieder vom “Ist doch klar, sowas macht doch keiner”-Typus. Leider sieht die Sache ganz anders aus. Folgendes sehe ich JEDEN Tag häufiger:

ififif 1

Ganz schlaue Experten gehen sogar einen Schritt weiter und optimieren die Klammern weg, weil es Tipparbeit spart und “sinniger” erscheint:

ififif 2

Ich weiss nicht wie es anderen “Durchschnittsprogrammierern” geht wenn sie so etwas sehen, ich jedenfalls habe das Gefühl das sich meine Retina ablöst… Für alle die noch nicht gesehen haben, warum dies Augenkrebs verursachen kann, hier nochmal der Hinweis: Es gibt für logische Ausdrücke Boolsche-Operatoren. Jede Programmiersprache hält ein paar griffige bereit. Die Untermenge postuliere ich jetzt einfach mal auf UND, ODER und NICHT! In C/C++/C# werden sie mit &&, || bzw. ! ausgeschrieben. Eine saubere Formulierung dieser Abfrage wäre somit:

ififif 3

Eine Ausrede die ich diesbezüglich nicht mehr hören kann ist: Ja, früher hat ja in den if’s noch mehr dringestanden. Das ist dann alles nach und nach rausgefallen. DAS IST KEINE AUSREDE! DAS IST BULLSHIT! Wenn ich etwas aus/in einer if (oder sonstwo) lösche/ändere/hinzufüge, habe ich nicht nur das Privileg sondern auch die hoheitliche Pflicht sich den umgebenen Quellcode anzuschauen. Und sollte ich durch meine Änderungen ein solches Konstrukt “hinterlassen”, bin ich nicht besser als jener, der sowas initial in die Tastatur rotzt.

ANSI-C – Darf ich alles?

Donnerstag, 15. März 2007

Dieser kleine Beitrag soll verdeutlichen, auch wenn ein ANSI-C Compiler Quellcode fehlerfrei übersetzt, es noch lange nicht heisst, dass die Ergebnisse immer vorhersagbar sind. Dazu betrachten wir die folgende, vermutlich aus ästhetischen Gründen entstandene Anweisung (x sei mal 1):

y = x++ + ++x;

Was könnten wir nach dieser Anweisung in y erwarten? Wir könnten zum Einen von links nach rechts durchgehen und sagen: x ist erst 1, also steht schonmal 1 + ++x dort. Das ++x wird aber vor der Addition erhöht, also ist es schon 2. Somit erwarten wir 1 + 2 = 3. x wird danach nochmal hochgezählt und hätte nach dieser Anweisung 4.

Zum Anderen könnten wir aber auch sagen, dass das x vor dem gesamten Ausdruck inkrementiert wird. Also hätten wir 2 + 2 = 4 für y. Und x wäre nachher sogar 5.

Dies verdeutlicht, obwohl diese Anweisung von jedem ANSI-C Compiler übersetzt werden kann, kann Ergebnis nicht vorhergesagt werden. Solche Sonderfälle werden in diesen Standards nicht aufgeführt, da es viel zu viele wären. Der Programmierer hat dafür zu sorgen, das dem Compiler klipp und klar ist, was von ihm erwartet wird. Solche Fehler können auch noch Unscheinbarer sein. Oben fällt die ungewöhnliche Struktur ja gleich ins Auge. Aber es kann auch einfacher und optisch “verschleiert” vorkommen. Ein Beispiel, wo es nicht sofort ins Auge gesprungen wäre:

z = ( x + y + z ) / ++x;

Also immer ein wachsames Auge für solche Unstimmigkeiten haben. Und selbst wenn der Compiler solche Anweisungen eindeutig auflösen könnte, sollte man auf die Komplexität und Lesbarkeit achten. Denn ich möchte persönlich keine Anweisung ala

++x += –x *= ++x -= -x;

verstehen müssen. Auch wenn es ein ANSI-Compiler ohne murren übersetzt.

do while – Schleife

Donnerstag, 15. März 2007

In diesem Beitrag geht es um ein do – while Konstrukt, welches besser formuliert werden kann (gefunden in freier Wildbahn). Ich habe den Code-Teil wieder auf die wesentliche Struktur runtergebrochen:

do while hrmpf
Bevor Ihr weiterlest, könntet Ihr euch mal überlegen wie dieses Schleifenkonstrukt besser formuliert werden könnte.

(weiterlesen…)