[C/C++] const auf integrale typen in einer Funktion sinnvoll?
-
hustbaer schrieb:
;fricky schrieb:
hustbaer schrieb:
ok, fricky, sorry. mein fehler.
kreativen const-schummel code zu schreiben ist natürlich produktiver als sauber zu programmieren. wie konnte ich nur was anderes glauben.wieso 'schummel'?
const wegcasten, und dann etwas modifizieren, ist schummeln.
nö, wenn du z.b. 'ne funktion aufrufen willst, bei der das 'const' fehlt, die aber definitiv keine schreibzugriffe über diesen pointer macht, musstes wegcasten. das ist nichts schlimmes und funktioniert auch.
hustbaer schrieb:
schnittstellen müssen sowieso gut dokumentiert sein, wenn andere damit arbeiten sollen. 'const' hilft dabei nur bedingt.
was heisst bedingt? bedingt wie "hilft viel, aber ist nicht 100% ausreichend"? oder bedingt wie "ist so-gut-wie egal"? sag mal konkret was du meinst.
das kommt drauf an. wenn 'const' logisch passt, unterstützt es die lesbarkeit. wenn aber z.b. da steht: 'void funktion (const void *p)', dann ist klar, dass das interface irgendwie mist ist, weil mit ziemlicher sicherheit im innern gecastet wird.
btw, nochwas zu deinen casting-verbotsregeln 'wer const wegcastet wird gefeuert', eine kleine quizfrage: wie bekommt man 'const' weg, ohne irgendeinen cast zu benutzen.?
-
Gar nicht(!), sondern indem man 100-prozentige 'const-correctness' verwendet (halbe oder dreiviertel const-correctness ist Frickelei -)
-
Th69 schrieb:
Gar nicht(!)
doch, 'entconsten' geht ohne cast. wer errät den trick (ist garnicht so schwer)?
-
;fricky schrieb:
nö, wenn du z.b. 'ne funktion aufrufen willst, bei der das 'const' fehlt, die aber definitiv keine schreibzugriffe über diesen pointer macht, musstes wegcasten. das ist nichts schlimmes und funktioniert auch.
Doch, das ist ein schlimmer Designfehler, der bei durchdachter Programmierung nicht auftritt. Dass gewisse Bibliotheken schlecht programmiert sind, rechtfertigt
const_cast
nicht per se.;fricky schrieb:
das kommt drauf an. wenn 'const' logisch passt, unterstützt es die lesbarkeit. wenn aber z.b. da steht: 'void funktion (const void *p)', dann ist klar, dass das interface irgendwie mist ist, weil mit ziemlicher sicherheit im innern gecastet wird.
Wieso, es kann ja auch sein, dass nur lesend zugegriffen wird, auch wenn
p
in einen Typzeiger gecastet werden muss. Ich finde Funktionen, die bei ihrer Schnittstelle heucheln, als würden sie Argumente nicht verändern, völlig daneben.;fricky schrieb:
doch, 'entconsten' geht ohne cast. wer errät den trick (ist garnicht so schwer)?
Das wäre eine Möglichkeit:
union conster { const int* m; int* n; }; int main() { const int a = rand() >= 0 ? 5 : 2; // damit kein konstanter Ausdruck conster c; c.m = &a; (*c.n) = 7; }
-
Nexus schrieb:
;fricky schrieb:
nö, wenn du z.b. 'ne funktion aufrufen willst, bei der das 'const' fehlt, die aber definitiv keine schreibzugriffe über diesen pointer macht, musstes wegcasten. das ist nichts schlimmes und funktioniert auch.
Doch, das ist ein schlimmer Designfehler, der bei durchdachter Programmierung nicht auftritt. Dass gewisse Bibliotheken schlecht programmiert sind, rechtfertigt
const_cast
nicht per se.ich dachte eigentlich, der const_cast wäre genau für sowas gut, nämlich ein nachträglich ge-constetes objekt mal wieder zu ent-consten. doof ist natürlich, dass man in einer funktion selbst nicht erkennen kann, ob es sich bei dem vom aufrufer erhaltenen pointer nur um eine 'verkleidung', oder um ein tatsächlich konstantes objekt handelt, denn im zweiten fall wäre ein const-wegcast ja undefiniert.
Nexus schrieb:
;fricky schrieb:
doch, 'entconsten' geht ohne cast. wer errät den trick (ist garnicht so schwer)?
Das wäre eine Möglichkeit:
union conster { const int* m; int* n; }; ...
genau das meinte ich. weitere möglichkeiten gibts wohl nicht, oder kennt noch jemand eine?
jedenfalls sollte husti auch unions in seine verbotsliste aufnehmen.
-
;fricky schrieb:
ich dachte eigentlich, der const_cast wäre genau für sowas gut, nämlich ein nachträglich ge-constetes objekt mal wieder zu ent-consten.
Der Const-Cast ist mehr ein Workaround für bereits schlechtes Design als ein wirklich oft sinnvoll eingesetztes Sprachmittel. Was hat Const-Correctness für einen Sinn, wenn man sich nicht daran hält? Wenn man ein Objekt als
const
deklariert, geht man davon aus, dass es nicht geändert wird. Daran kann man sich gefälligst halten...;fricky schrieb:
genau das meinte ich. weitere möglichkeiten gibts wohl nicht, oder kennt noch jemand eine?
Gibt noch ein paar Möglichkeiten, besonders mit Strukturen (obwohl diese sehr ähnlich sind). Du hast zu wenig Fantasie!
Dass da recht schnell undefiniertes Verhalten dazu kommt, sollte klar sein.// 1) int n = 1; const int m = 5*n; *(&n + (&m - &n)) = 42; // 2) const int o = 5*n; struct { int* n; const int* m; } z = {&n, &o}; **(&z.n + 1) = 42; // 3) struct { int n; const int m; } a = {1, 5}; *(&a.n + 1) = 42; // 4) struct tmp { const int p; }; tmp b = {5}; tmp h = {42}; new (&b) tmp(h); // 5) struct hacker { int q; }; tmp c = {5}; reinterpret_cast<hacker*>(&c)->q = 42; // 6) tmp d = {5}; memcpy(&d, &h, sizeof(h)); std::cout << m << " " << o << " " << a.m << std::endl; std::cout << b.p << " " << c.p << " " << d.p << std::endl;
-
Nexus schrieb:
Der Const-Cast ist mehr ein Workaround für bereits schlechtes Design als ein wirklich oft sinnvoll eingesetztes Sprachmittel. Was hat Const-Correctness für einen Sinn, wenn man sich nicht daran hält? Wenn man ein Objekt als const deklariert, geht man davon aus, dass es nicht geändert wird. Daran kann man sich gefälligst halten...
stimmt, aber in const-korrektem code darfste nie einen const-pointer an eine nicht-const funktion übergeben, obwohl du 100% weisst, dass sie deine daten nicht anrührt. das ist eine grosse einschränkung. dann vielleicht besser ganz auf const verzichten. ich z.b. verwende 'const' nur, um compiler und linker unter die arme zu greifen, um (auf 'nem embedded system mit wenig RAM) dafür zu sorgen, das unveränderliche daten im Flash und nicht im RAM landen.
Nexus schrieb:
Gibt noch ein paar Möglichkeiten, besonders mit Strukturen (obwohl diese sehr ähnlich sind).
1,2 und 3 kann ich nicht gelten lassen, weil die auch daneben zielen können. 5 hat 'nen cast drin, aber kein 'const-cast', d.h. hb's verbotsliste könnte jetzt so aussehen:
kündigungsgründe für uneinsichtige c++ hacker sind:
1. alle casts
2. memcpy
3. unions
4. placement new
5. anlegen eigener strukturen
^^ und da wir das ja nicht wollen, schlagen wir am besten den GCC-entwicklern vor, dieses feature aufzunehmen. der switch könnte heissen: '-enable_coughbear_blacklist' *fg*
-
;fricky schrieb:
hustbaer schrieb:
;fricky schrieb:
hustbaer schrieb:
ok, fricky, sorry. mein fehler.
kreativen const-schummel code zu schreiben ist natürlich produktiver als sauber zu programmieren. wie konnte ich nur was anderes glauben.wieso 'schummel'?
const wegcasten, und dann etwas modifizieren, ist schummeln.
nö, wenn du z.b. 'ne funktion aufrufen willst, bei der das 'const' fehlt, die aber definitiv keine schreibzugriffe über diesen pointer macht, musstes wegcasten. das ist nichts schlimmes und funktioniert auch.
dann ist es aber auch kein problem, und man kann sich weiterhin auf const verlassen. genau das hast du ja bestritten, und ich versuche dir zu erklären, dass es unfug ist so zu programmieren, dass man sich nicht darauf verlassen kann. lies mal auf seite 6 wenn deine erinnerung nichtmehr ausreicht.
hustbaer schrieb:
schnittstellen müssen sowieso gut dokumentiert sein, wenn andere damit arbeiten sollen. 'const' hilft dabei nur bedingt.
was heisst bedingt? bedingt wie "hilft viel, aber ist nicht 100% ausreichend"? oder bedingt wie "ist so-gut-wie egal"? sag mal konkret was du meinst.
das kommt drauf an. wenn 'const' logisch passt, unterstützt es die lesbarkeit. wenn aber z.b. da steht: 'void funktion (const void *p)', dann ist klar, dass das interface irgendwie mist ist, weil mit ziemlicher sicherheit im innern gecastet wird.
klar wird vermutlich irgendwo gecastet, aber das const wird hoffentlich nicht weggecastet.
btw, nochwas zu deinen casting-verbotsregeln 'wer const wegcastet wird gefeuert'
hab ich nie geschrieben.
eine kleine quizfrage: wie bekommt man 'const' weg, ohne irgendeinen cast zu benutzen.?
irrelevant, da das noch viel schlimmere hacks sind, als const wegcasten. wer sowas schreibt, nur um irgendwelche regeln zu umgehen, gehört erst recht entlassen.
-
;fricky schrieb:
Th69 schrieb:
Gar nicht(!)
doch, 'entconsten' geht ohne cast. wer errät den trick (ist garnicht so schwer)?
einfacher:
#define const void foo(const int* v) { *v = 5; }
-
tntnet schrieb:
#define const void foo(const int* v) { *v = 5; }
^^auch nicht schlecht, aber manche compiler lassen's nicht zu, wenn man schlüsselwörter mit #define verändern will.
-
;fricky schrieb:
kündigungsgründe für uneinsichtige c++ hacker sind:
1. alle casts
2. memcpy
3. unions
4. placement new
5. anlegen eigener strukturenoder:
kündigungsgrund für uneinsichtige c++ hacker ist:
Code der undefiniertes Verhalten beinhaltet oder auslösen kann.
(und dazu gehört: innerhalb der Funktion einem Argument das const wegcasten und reinschrieben)
-
;fricky schrieb:
tntnet schrieb:
#define const void foo(const int* v) { *v = 5; }
^^auch nicht schlecht, aber manche compiler lassen's nicht zu, wenn man schlüsselwörter mit #define verändern will.
Wie schaffen die das? Es ist doch der Präprozessor, der die Ersetzung macht. Der Compiler sieht das doch gar nicht mehr.
Übrigens noch übler finde ich:
#define private public #include <someclassfile.h>
Das habe ich mal im echten Code gesehen. Wäre ein Fall für Daily WTF.
-
Das habe ich mal im echten Code gesehen. Wäre ein Fall für Daily WTF.
Ich hoffe jetzt mal, dass du den dafür zuständigen Programmierer aufgespürt hast und ihm ordentlich eine verpasst hast.
Oder noch besser mit ihm das hier gemacht:
#define zustaendiger_programmierer void
-
drakon schrieb:
Das habe ich mal im echten Code gesehen. Wäre ein Fall für Daily WTF.
Ich hoffe jetzt mal, dass du den dafür zuständigen Programmierer aufgespürt hast und ihm ordentlich eine verpasst hast.
Oder noch besser mit ihm das hier gemacht:
#define zustaendiger_programmierer void
Oder man nimmt einfach eine vernueftige Sprache fuer das Problem, anstelle kostbare Entwicklungszeit mit dem Erstellen, der Kontrolle und der Durchsetzung idiotischen Regeln zu verplempern. Ernsthaft, als Entwickler sollte man sich doch nicht mit Politik beschaeftigen. Die Sprache selber sollte die Regeln festlegen und von dem Compiler automatisch ueberprueft und durchgesetzt werden.
Ansonsten muss man sich ein Regelwerk einfallen lassen, was alles verboten ist, und dann haellt sich einer nicht daran wegen *Besonderer-Grund-#465* und man verbringt die Haelfte der Zeit mit der Suche nach *Besonderer-Grund-#465-Bug #1, #2, #3, #4, #5...*. Als Bonus darf man sich Code-Validierer schreiben, die versuchen das Regelwerkt irgendwie automatisch zu kontrollieren, was eigentlich die Aufgabe der Compiler- und Sprach-Designer war.
-
DEvent schrieb:
Oder man nimmt einfach eine vernueftige Sprache fuer das Problem, anstelle kostbare Entwicklungszeit mit dem Erstellen, der Kontrolle und der Durchsetzung idiotischen Regeln zu verplempern.
wahrscheinlich finden es manche einfach spannender so.
-
DEvent schrieb:
Oder man nimmt einfach eine vernueftige Sprache fuer das Problem, anstelle kostbare Entwicklungszeit mit dem Erstellen, der Kontrolle und der Durchsetzung idiotischen Regeln zu verplempern.
Zeig mir eine Sprache wo man keinen Mist bauen kann und die trotzdem die nötige Flexibilität mitrbingt.
-
pumuckl schrieb:
Zeig mir eine Sprache wo man keinen Mist bauen kann und die trotzdem die nötige Flexibilität mitrbingt.
reicht auch eine sprache, die ebenso flexibel ist, aber in der man weniger mist bauen kann?
-
pumuckl schrieb:
DEvent schrieb:
Oder man nimmt einfach eine vernueftige Sprache fuer das Problem, anstelle kostbare Entwicklungszeit mit dem Erstellen, der Kontrolle und der Durchsetzung idiotischen Regeln zu verplempern.
Zeig mir eine Sprache wo man keinen Mist bauen kann und die trotzdem die nötige Flexibilität mitrbingt.
Die wirklich interessante Frage ist, wie viel Flexibilität man ueberhaupt braucht.
Um einen Nagel in die Wand zu schlagen brauche ich nur einen Hammer, aber manche nehmen eine Sprache, die die Moeglichkeit bietet spezialisierte Haemmer zu schreiben. Ist ja schoen, dass du fuer jeden Spezialfall einen neuen Hammer implementieren kannst, aber die Aufgabe war einen Nagel einzuschlagen.
Wenn man sich doch wenigstens auf const-correctnes verlassen koennte. Aber man kann es weg-casten, mit structs wegtricksen und mit define ganz wegmachen. Alleine die Existens von const_cast zeigt doch schon, dass const-correctnes in manchen Situationen keinen Sinn macht. So kann man sich fragen, ob so etwas ueberhaupt in einer Sprache sinnvoll ist.
Volatile macht z.B. immer Sinn, so gibt es auch keinen volatile_cast, ebenso wenig einen static_cast. Ebenso macht private und protected immer Sinn, es gibt ja auch keinen private_cast oder protected_cast. Wieso dann bei const?
-
DEvent schrieb:
Volatile macht z.B. immer Sinn, so gibt es auch keinen volatile_cast, ebenso wenig einen static_cast.
doch, c++ hat einen 'static_cast', aber der castet nicht zwischen static und nicht-static hin und her, sondern er heisst offenbar so, damit man ihn vom 'dynamic_cast' unterscheiden kann. ja, ich weiss, in C++ schon alles ziemlich äääh.. seltsam.
-
Volatile macht z.B. immer Sinn
Unsinn, es macht nur in Spezialfällen Sinn.
Ebenso macht private und protected immer Sinn
Auch Unsinn. Auf protected könnte man verzichten.
Was deine Hämmer angeht ist das so eine Sache. Spezialhämmer skalieren schlecht. Wenn man bis jetzt nur Vogelhäuschen gebaut hat aber jetzt nen Pfahl in den Boden rammen soll steht man mit deinem Haushaltshammer dumme da. Hätte man eine flexiblere Hammersprache könnte man sich nen Vorschlaghammer schreiben und weitermachen.