Casten mit Carsten

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
AnGaiNoR
Beiträge: 212
Registriert: Sa Jul 19, 2008 7:07 pm
Wohnort: Dresden

Casten mit Carsten

Beitrag von AnGaiNoR » Mi Jul 23, 2008 12:10 pm

Unter der Prioritätentabelle steht, dass Casten ein Zeichen schlechten Programmierstils ist.
Meiner Meinung nach kommt man manchmal ohne Ca(r)sten gar nicht aus.

Beispiel: Die (Windows-)Funktion zum auslesen eines Registry-Wertes

Code: Alles auswählen

WINADVAPI
LONG
APIENTRY
RegQueryValueExA (
    __in HKEY hKey,
    __in_opt LPCSTR lpValueName,
    __reserved LPDWORD lpReserved,
    __out_opt LPDWORD lpType,
    __out_bcount_opt(*lpcbData) LPBYTE lpData,
    __inout_opt LPDWORD lpcbData
    );
Das Argument lpData ist immer ein Zeiger auf ein BYTE-Array.
Wenn ich aber eine Zeichenkette auslesen will, dann muss ich einen TypeCast (reinterpret_cast) verwenden.
Physics is like sex: sure, it may give some practical result, but that's not why we do it.
(Richard P. Feynman)

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: Type-Casts

Beitrag von Kerli » Mi Jul 23, 2008 12:25 pm

AnGaiNoR hat geschrieben:Unter der Prioritätentabelle steht, dass Casten ein Zeichen schlechten Programmierstils ist.
Meiner Meinung nach kommt man manchmal ohne Ca(r)sten gar nicht aus.

Beispiel: Die (Windows-)Funktion zum auslesen eines Registry-Wertes

Code: Alles auswählen

WINADVAPI
LONG
APIENTRY
RegQueryValueExA (
    __in HKEY hKey,
    __in_opt LPCSTR lpValueName,
    __reserved LPDWORD lpReserved,
    __out_opt LPDWORD lpType,
    __out_bcount_opt(*lpcbData) LPBYTE lpData,
    __inout_opt LPDWORD lpcbData
    );
Das Argument lpData ist immer ein Zeiger auf ein BYTE-Array.
Wenn ich aber eine Zeichenkette auslesen will, dann muss ich einen TypeCast (reinterpret_cast) verwenden.
Wer sagt denn, dass die WinAPI gut programmiert ist :D
Nein Spaß beiseite. Es gibt natürlich auch Fälle in denen es durchaus angebracht ist casts zu verwenden, wenn man allerdings zu häufig davon Gebrauch machen muss, dann hat man wahrscheinlich irgendwo einen Designfehler drinnen.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Type-Casts

Beitrag von Xin » Mi Jul 23, 2008 1:30 pm

AnGaiNoR hat geschrieben:Unter der Prioritätentabelle steht, dass Casten ein Zeichen schlechten Programmierstils ist.
Meiner Meinung nach kommt man manchmal ohne Ca(r)sten gar nicht aus.

Beispiel: Die (Windows-)Funktion zum auslesen eines Registry-Wertes
Aber das ist doch kein Widerspruch?

Wenn es ein allgemein anerkanntes Beispiel für total verkorkstes Softwaredesign gibt, dann steht die WinAPI definitiv in den Top10 und dort besetzt sie alle 10 Plätze mit großem Abstand zum nächst schlechtesten Design.

Carsten kann programmieren, der braucht nicht zu casten.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C:Ausdrücke

Beitrag von Dirty Oerti » Mi Jul 23, 2008 1:31 pm

Ich finde Casten an sich eigentlich eine sehr gute Möglichkeit...
Und für schlechten Programmierstil halte ich es erst recht nicht.

Manchmal geht's sogar nicht ohne... da braucht man dann einen Cast.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C:Ausdrücke

Beitrag von Xin » Mi Jul 23, 2008 1:34 pm

Dirty Oerti hat geschrieben:Ich finde Casten an sich eigentlich eine sehr gute Möglichkeit...
Und für schlechten Programmierstil halte ich es erst recht nicht.
Gute Möglichkeit für was?
Dirty Oerti hat geschrieben:Manchmal geht's sogar nicht ohne... da braucht man dann einen Cast.
Es geht immer ohne Cast.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

AnGaiNoR
Beiträge: 212
Registriert: Sa Jul 19, 2008 7:07 pm
Wohnort: Dresden

Re: C:Ausdrücke

Beitrag von AnGaiNoR » Mi Jul 23, 2008 1:45 pm

Xin hat geschrieben:Es geht immer ohne Cast.
Na dann bräuchtest du für meine EINE Beispielfunktion aber 6.
Physics is like sex: sure, it may give some practical result, but that's not why we do it.
(Richard P. Feynman)

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C:Ausdrücke

Beitrag von Xin » Mi Jul 23, 2008 1:53 pm

AnGaiNoR hat geschrieben:
Xin hat geschrieben:Es geht immer ohne Cast.
Na dann bräuchtest du für meine EINE Beispielfunktion aber 6.
Nein, Du brauchst einen Entwickler, der sich auf's Wesentliche konzentrieren kann.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Ausdrücke in C

Beitrag von fat-lobyte » Mi Jul 23, 2008 4:34 pm

Kerli hat geschrieben:
AnGaiNoR hat geschrieben:Meinst du mit "Ausdrücke" etwa "Regular Expressions"?
Damit hab ich mich leider noch nicht beschäftigt, aber wenn ihr es schafft mich dazu anzuregen... ^^
Nein mit Ausdrücken ist da etwas anderes gemeint - In C/C++ verwendet man 'regular expressions' nicht so oft, weil es keine solchen Funktionen in der Standardbibliothek gibt.
NOCH gibt es die nicht. Ab ca. 2009 gibts dann nen neuen Standard, wo es dann hochoffiziell Regular Expressions gibt. Manche Compiler haben die Libs bereits, und zwar im namespace std::tr1.

Zum Thema Casten:
Manchmal geht es einfach nicht ohne. Beispiel Nr. 1:

Code: Alles auswählen

#include <stdlib.h>

...
int* integer_array = (int*) malloc(ARRAYSIZE*sizeof(int));
Beispiel Nr. 2:

Code: Alles auswählen

/* Ich will einfach nur einen Puffer von bytes haben,
* zum beispiel um Netzwerkpakete zusammenzubauen
*/
unsigned char buffer[BUFSIZE];

*(unsigned int*) buffer = packet_length;
*((unsigned short) (buffer+sizeof(unsigned int)) = header_length;
...
Beispiel Nr 3, jetzt aus C++:

Code: Alles auswählen

struct Base 
{
    bool is_A;

    virtual void boringFunction() = 0;

    Base(bool _is_A)
        : is_A(_is_A)
    {}

};

struct DerivedA 
{
    DerivedA()
        : Base(true)
    {}

    virtual void boringFunction()
    {}

    void wickedFunction()
    {}
}

struct DerivedB 
{
    DerivedB()
        : Base(false)
    {}

    virtual void boringFunction()
    {}

    void coolFunction()
    {}
}

void handler(Base* base)
{
    if (base->is_A)
    {
        dynamic_cast<DerivedA>(base)->wickedFunction();
    }
    else 
    {
        dynamic_cast<DerivedA>(base)->coolFunction();
    }
}
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8489
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ausdrücke in C

Beitrag von Xin » Mi Jul 23, 2008 6:49 pm

fat-lobyte hat geschrieben:Zum Thema Casten:
Manchmal geht es einfach nicht ohne. Beispiel Nr. 1:

Code: Alles auswählen

#include <stdlib.h>
...
int* integer_array = (int*) malloc(ARRAYSIZE*sizeof(int));
Wozu gibt es in C++ new?

Ansonsten:

Code: Alles auswählen

union IntegerPointer
{
  void * MemoryHandling;
  int * IntegerArray;
};

union IntegerPointer intP;

intP.MemoryHandling = malloc( ARRAYSIZE * sizeof( int ) );
intP.IntegerArray[0] = 1;
Mit dem Cast darf man integer_array auch mal nach (char *) konvertieren und auf einen String zeigen lassen. union IntegerPointer lässt das nicht zu.
fat-lobyte hat geschrieben:Beispiel Nr. 2:

Code: Alles auswählen

/* Ich will einfach nur einen Puffer von bytes haben,
* zum beispiel um Netzwerkpakete zusammenzubauen
*/
unsigned char buffer[BUFSIZE];

*(unsigned int*) buffer = packet_length;
*((unsigned short) (buffer+sizeof(unsigned int)) = header_length;
...
C++ Lösung: Klasse erstellen, bestehend aus eigenen Longs, die sich als char-Array zurückgeben lassen.
C Lösung: Funktionen verwenden, die klare Aussagen treffen, was sie tun. Hier könnte man sich wieder mit Unions behelfen, aber hier würde ich Casting akzeptieren, wenn es nur in den passenden Funktionen stattfinden würde.

Code: Alles auswählen

WriteUnsignedint( char ** buffer, unsigned int l )
{
  *((unsigned int *) *buffer) = l;
  *buffer += sizeof( long );
}
WriteUnsignedShort( char ** buffer, unsigned short s )
{
  *((unsigned int *) *buffer) = s;
  *buffer += sizeof( short );
}
...
unsigned char buffer[BUFSIZE];
unsigned char ** bufferPos = &buffer;

WriteUnsignedLong( bufferPos, packed_length );
WriteUnsignedShort( bufferPos, header_length );
fat-lobyte hat geschrieben: Beispiel Nr 3, jetzt aus C++:

Code: Alles auswählen

struct Base 
{
    bool is_A;

    virtual void boringFunction() = 0;

    Base(bool _is_A)
        : is_A(_is_A)
    {}

};

struct DerivedA 
{
    DerivedA()
        : Base(true)
    {}

    virtual void boringFunction()
    {}

    void wickedFunction()
    {}
}

struct DerivedB 
{
    DerivedB()
        : Base(false)
    {}

    virtual void boringFunction()
    {}

    void coolFunction()
    {}
}

void handler(Base* base)
{
    if (base->is_A)
    {
        dynamic_cast<DerivedA>(base)->wickedFunction();
    }
    else 
    {
        dynamic_cast<DerivedA>(base)->coolFunction();
    }
}
Grober Designfehler...

Code: Alles auswählen

struct Base 
{
    bool is_A;

    virtual void boringFunction() = 0;

    Base(bool _is_A)
        : is_A(_is_A)
    {}

    virtual void handler() = 0;
};

struct DerivedA : public Base // <- gehe ich mal von aus...
{
    DerivedA()
        : Base(true)
    {}

    virtual void boringFunction()
    {}

    void wickedFunction()
    {}

    void handler()
    {
      wickedFunction();
    }
}

struct DerivedB : public Base
{
    DerivedB()
        : Base(false)
    {}

    virtual void boringFunction()
    {}

    void coolFunction()
    {}

    void handler()
    {
      coolFunction();
    }

}
Casten ist immer nur ein Armutszeugnis für einen Entwickler. In Beispiel 2 ist casten eine Vereinfachung, Lösung 1 würde hier auch greifen. Lösung 1 ist im letztendlich das gleiche wie Casten, aber es ist vorher klar, dass man nicht überall hinkonvertieren kann, sondern nur zu festgelegte Typen.
Casten in C++ ist ein Zeichen ist so gut wie überhaupt nicht mehr notwendig. Es gibt Fälle mit Templates, da komme ich nicht um Casten rum, um Redundanz zu vermeiden. Bevor ein Cast verwendet wird, sollte man lieber mal ein paar Tage in sich gehen und überlegen, was es für Alternativen gibt.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Ausdrücke in C

Beitrag von Dirty Oerti » Mi Jul 23, 2008 7:11 pm

Xin hat geschrieben:
fat-lobyte hat geschrieben:Zum Thema Casten:
Manchmal geht es einfach nicht ohne. Beispiel Nr. 1:

Code: Alles auswählen

#include <stdlib.h>
...
int* integer_array = (int*) malloc(ARRAYSIZE*sizeof(int));
Wozu gibt es in C++ new?
Was ist aber, wenn du C schreiben MUSST ?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Antworten