Explizite Typenkonvertierung - Wozu?
-
groovemaster schrieb:
Da haben zB einige Funktionen schon mal LPTSTR als Parameter, obwohl es eigentlich LPCTSTR sein müsste.
Zum Beispiel? Mir fällt gerade nichts ein...
-
Mir fällt als Beispiel bloss CreateProcess ein. Wobei das ein Fall ist wo man tunlichst nicht casten sollte, sondern eine temporäre Kopie in einer Wrapper-Funktion anlegen.
Ansonsten hab ich das viel öfters in irgendwelchen anderen Libraries/APIs/Interfaces/... gesehen als in der WinAPI.
-
Mir fällt als Beispiel OpenPrinter ein.
-
Jochen Kalmbach schrieb:
Zum Beispiel? Mir fällt gerade nichts ein...
Wie hustbaer schon sagte, CreateProcess würde auch mir spontan einfallen. Wobei ich mich etwas korrigieren muss. Es sind nicht unbedingt nur Funktionen, auch Strukturen sind diesbezüglich hin und wieder inkonsistent. Spontan würden mir Sachen wie LVITEM oder TCITEM einfallen. LPTSTR ist ja iO, wenn ich ein Element abrufen möchte. Wenn ich es aber setzen oder ein neues einfügen möchte, kann ich LPTSTR nun wirklich nicht gebrauchen.
-
Die Anmerkung war doch:
Da haben zB einige Funktionen schon mal LPTSTR als Parameter, obwohl es eigentlich LPCTSTR sein müsste.
Dokumentiert ist es aber richtig... somit ist auch ein cast hier *nie* nötig.
Das war doch der Ursprung der Frage, oder?Natürlich ist es historisch bedingt und auch sehr unschön, das dort (CreateProcess) LPTSTR steht... gar keine Frage... aber was das mit dem casten zu tun hat ist mir etwas schleierhaft...
-
Weil man hin und wieder Code sieht, wo eben const Ausdrücke aufgrund der teilweise vorhandenen Inkonsistenzen non-const gecastet werden.
Nur mal ein Beispiel aus dem Pov-Ray Projekt, welches mir kürzlich über den Weg gelaufen ist.
// editorinterface.cpp void InsertTab (LPCSTR title) { // ... TCITEM item ; // ... item.pszText = (LPSTR) title ; }Sowas beherbergt potenzielle Fehler und kann zu undefiniertem Verhalten führen.
Ich will gar nicht grossartig darauf rumreiten. Mir ist schon bewusst, dass dies historisch bedingt ist. Unschön bleibt es aber allemal und erschwert die Entwicklung teils unnötig.
-
Ja... da geb ich Dir ja recht... aber eigentlich müsste man so wie "hustbaer" geschrieben hat hier ein _strdup machen...
Das mit TCITEM ist ja wirklich etwas unschön... da die Struktur sowohl zum "setzen" (LPCTSTR) als auch zum "zurückgeben" (LPTSTR) verwenden kann...
Als API-Designer hätte ich mich wohl auch für den Kompromiss entscheiden; alternativ hätte man zwei "gleiche" Strukturen definieren müssen mit zwei unterschiedlichen Funktionen...
Aber da auf der "SendMessage" Ebene ja eh alles gecastest wird (API-bedingt), ist Windows eh sehr unschön...
-
Jochen Kalmbach schrieb:
Ja... da geb ich Dir ja recht... aber eigentlich müsste man so wie "hustbaer" geschrieben hat hier ein _strdup machen...
Mehr als ein wenig effizienter Workaround ist das aber leider auch nicht. Eine saubere Lösung sieht für mich immer noch etwas anders aus.
-
groovemaster schrieb:
Jochen Kalmbach schrieb:
Ja... da geb ich Dir ja recht... aber eigentlich müsste man so wie "hustbaer" geschrieben hat hier ein _strdup machen...
Mehr als ein wenig effizienter Workaround ist das aber leider auch nicht. Eine saubere Lösung sieht für mich immer noch etwas anders aus.
Die Lösung ist IMO sehr sauber. CreateProcess ist schweine-langsam, da kannste schonmal Kaffee trinken gehen bevor sich da was rührt. Von daher total egal ob man 1x Speicher anfordert und 1x kopiert. Alternativ kann man noch die Länge checken, und z.B. alles was < 4K ist vom Stack holen (lokales Array oder alloca).
Im Fall CreateProcess fände ich es aber total unangebracht. std::string bzw. strdup sind viel einfacher, und für den Fall total ausreichend. Daher würde ich alles andere als "unsauber" bezeichnen, weil es unnötig komplex ist.
-
Naja, für den Fall von CreateProcess *musst* Du sogar ein strdup verwenden, da der String _wirklich_ beschrieben wird!
Das geht noch mit der Ansi-Funktion (CreateProcessA) gut, weil intern sowieso ein beschreibbarer Puffer erzeugt wird (da nach Unicode umgewandelt wird), aber bei der Unicode-Version (CreateProcessW) stürzt Dein Programm ab, wenn Du ein (nicht beschreibarer String) übergibst... (ab VS2005 werden String-Literale in den Read-Only-Speicher gelegt!)
-
Er.
std::string in meinem Beitrag oben ist natürlich Unsinn - da man einen beschreibbaren String braucht, sollte man wenn dann std::vector verwenden.
-
hustbaer schrieb:
Die Lösung ist IMO sehr sauber. CreateProcess ist schweine-langsam, da kannste schonmal Kaffee trinken gehen bevor sich da was rührt. Von daher total egal ob man 1x Speicher anfordert und 1x kopiert.
strdup selbst ist schon unsauber. Nicht umsonst ist diese Funktion nicht im C Standard enthalten. Und wie lange CreateProcess dauert, weisst du nicht. Für dich als Entwickler ist das erstmal eine Black Box. Von daher kann man nicht pauschal sagen, dass es egal ist.
Eine saubere Lösung schaut so aus, dass CreateProcess einen const Parameter entgegennimmt. Muss dieser verändert werden, dann auch innerhalb der Funktion. Für mich als Client besteht dafür keine Notwendigkeit.
Notfalls könnte man auch mit 2 Funktionen leben, eine für const und eine für non-const.
-
groovemaster schrieb:
hustbaer schrieb:
Die Lösung ist IMO sehr sauber. CreateProcess ist schweine-langsam, da kannste schonmal Kaffee trinken gehen bevor sich da was rührt. Von daher total egal ob man 1x Speicher anfordert und 1x kopiert.
strdup selbst ist schon unsauber. Nicht umsonst ist diese Funktion nicht im C Standard enthalten. Und wie lange CreateProcess dauert, weisst du nicht. Für dich als Entwickler ist das erstmal eine Black Box. Von daher kann man nicht pauschal sagen, dass es egal ist.
Unsinn.
Eine saubere Lösung schaut so aus, dass CreateProcess einen const Parameter entgegennimmt. Muss dieser verändert werden, dann auch innerhalb der Funktion. Für mich als Client besteht dafür keine Notwendigkeit.
Notfalls könnte man auch mit 2 Funktionen leben, eine für const und eine für non-const.CreateProcess nimmt aber nunmal keinen const Parameter. Ich meinte eine Wrapper Funktion ist eine saubere Lösung wenn man CreateProcess in dieser Form als gegeben annimmt.
Dass CreateProcess ein Design-Fehler ist hatten wir ja schon festgehalten, wieso also nochmal drauf rumreiten.
-
hustbaer schrieb:
Unsinn.
Nö.
hustbaer schrieb:
CreateProcess nimmt aber nunmal keinen const Parameter. Ich meinte eine Wrapper Funktion ist eine saubere Lösung wenn man CreateProcess in dieser Form als gegeben annimmt.
Dass CreateProcess ein Design-Fehler ist hatten wir ja schon festgehalten, wieso also nochmal drauf rumreiten.
Gute Frage. Aber wieso stellst du die mir?