Robert Bienert: String concat in c++

Beitrag lesen

Hallo Martin!

Warning: Mixing Pointers to signed and unsigned char (mir doch egal, ich mach doch keine Arithmetik damit!)

Und was passiert beim Dereferenzieren? Du vergleichst einen signed mit einem unsigned char, also einen Datentyp mit Wertebereich [-128,127] mit einem Datentyp des Wertebereiches [0,255].

Ja und? Deswegen sagte ich doch, ich betreibe keine Arithmetik damit, sondern verwende char (meistens) nur als Zeichen. Da ist es mir doch wurscht, ob signed oder unsigned.

Und warum dann nicht einheitlich char bzw. falls das Vorzeichen relevant ist halt (un)signed char? Diese Fehlermeldung ist übrigens vergleichbar mit folgender, da du Pointer auf unterschiedliche Objekte/Datentypen verwendest:

DWORD n;
  if (n==-1)
   { ... }
Warning: Constant out of range in comparison  (Scheißcompiler! Du sollst nicht denken, sondern machen!)

Du kannst doch die Warnungen deaktivieren. Diese Meldung ist gut, es gibt Compiler, die behandeln -1 bei einem DWORD als UINT32MAX-1, also eine sehr große Zahl.

Völlig schnurz. Wenn die CPU irgendwann über den Code herfällt, ist -1 genau dasselbe wie 0xFFFFFFFF, nur handlicher geschrieben.

Darauf kannst du dich allerdings im Allgemeinen nicht verlassen. Dein Code ist hochgradig plattform-spezifisch. Und wer garantiert dir, dass dein Programm nicht später auf einem Rechner mit einem Betriebssystem läuft, auf dem -1 ungleich 0xFFFFFFFF ist?

BYTE  *b;
DWORD *d;
  d = b;
Error: Type mismatch  (Herrje! Pointer ist pointer! Was ich damit mache, ist doch mein Problem!)

Wieso willst du so etwas machen, abgesehen davon, dass BYTE und DWORD unterschiedliche Größen haben? In diesem Beispiel zeigt d nach der Zuweisung nicht nur auf b, sondern auch noch auf die 3 Byte dahinter.

Das ist doch gerade das Schöne! Z.B. wenn ich -je nach Programmkontext- in bestimmten Speicherbereichen mal byteweise, mal doppelwortweise organisierte Daten habe.

Das kann man machen, du weißt aber schon, dass es auf 32-Bit-Computern deutlich schneller ist, auf je 4-Byte zuzugreifen als auf eines. Deshalb ist dort ein bool auch 4-Byte groß. Von bitweisem Datenzugriff ganz zu schweigen. Schreibst du Programme, die viel Arbeitsspeicher allokieren? Ansonsten denke ich, dass eine Geschwindigkeitsoptimierung sinnvoller ist.

[…] In den meisten Fällen kann man meiner Meinung nach auf die Hersteller von Betriebssystemen, Bibliotheken und Programmiersprachen vertrauen, dass sie keinen groben Schrott anbieten.

Nein, das nicht. Aber gerade die "Hersteller" von vorgefertigten Standardbibliotheken packen meist jede Menge tolle Flexibilität in ihre Funktionen, von der ich in einer bestimmten Anwendung vielleicht, wenn's viel ist, 10% ausnutze. Den Programmcode für den Rest schleppt meine Applikation nachher als Ballast mit.

Abgesehen von C++, macht sich das während der Laufzeit gravierend bemerkbar? Da gibt es genug andere Faktoren, die nicht nur dein Programm, sondern den kompletten Rechner ausbremsen können. Ich weiß, wenn jeder Programmierer denkt „heutige Rechner sind schnell genug“, hat der Anwender im Endeffekt wieder nichts davon, aber die Verhältnisse müssen meiner Meinung nach stimmen.

Im Übrigen finde ich dein Ballast-Argument nachvollziehbar in der Art, dass mir kleine, schlanke Bibliotheken deutlich lieber sind als „Wir haben die Lösung für alles“.

Dazu kommt, dass meiner Ansicht nach gerade durch die Kapselung bei der OOP der Überblick über die Zusammenhänge verlorengeht - ist jedenfalls mein persönlicher Eindruck.
Das soll er ja auch in gewisser Weise.

Ja, und das ist das Problem, wenn man mal fremde C++-Programme bekommt und erweitern oder anpassen möchte. Dann verbringt man Stunden und Tage damit, die Zusammenhänge zwischen den zahlreichen Klassen zu analysieren, um dann irgendwann festzustellen, dass die Struktur schon zu verfilzt ist, um die gewünschte Änderung mit vertretbarem Aufwand noch realisieren zu können, und dass man günstiger wegkommt, wenn man das Programm (oder zumindest Teile davon) von Grund auf neu aufsetzt.

Dieses Problem ist aus meiner Sicht nicht C++-spezifisch. Ich kenne C-Programme sowie Bibliotheken oder Teile davon, von denen man glaubt, dass man ihre Funktionalität benutzen könnte und nach langem hin und her feststellt, hätte man gleich das Rad neu erfunden, wäre man jetzt schon weiter.

Schau dir z.B. mal das Stream-Konzept von C++ an: Unabhängig davon, mit was für einem Ausgabe-„Gerät“ [...] später auf ein anderes „Gerät“ umsteige, brauche ich nur wenige Code-Zeilen zu ändern.

Das kann ich bei klassischer prozeduraler Programmierung aber auch, wenn ich die Aufrufschnittstellen meiner Funktionen sinnvoll festgelegt habe.

Da hast du vollkommen Recht. Aber sobald ich anfange, bestimmte Informationen an das letzlich verwendete „Subsystem“ bei jedem Funktionsaufruf mitschleppen zu müssen (File- oder Socket-Handles, Datenbank-Kennungen, …), wird für mich die ganze Sache lästig, weil dieser prozedurale Code objekt-orientiert ist, aber die Objekte und Methoden kompliziert umschrieben werden. Das kann man einfacher und eleganter mit echter OOP lösen.

Aber wie auch sonst kannst du nicht das schlampige Kodieren hauptsächlich der Programmiersprache anlasten.

Vielleicht nicht hauptsächlich. Aber wenn sie es noch begünstigt, oder sogar in Musterlösungen propagiert, finde ich das nicht wirklich okay.

Schau dir mal PHP an, das ist in meinen Augen an Verleitung zur Schlampigkeit nicht zu überbieten. Und es ist schon ein Unterschied, ob ein kleines Tool nur bei Vollmond zur Sommersonnenwende eine Lücke offenbart oder ob ein Webserver offen steht.
Außerdem denke ich, dass mit den neueren Sprachkonzepten in C++ wie z.B. Templates oder dem „Erzwingen“ expliziter Typecasts ein großer Schritt in Richtung sauberen Programmierens gegangen worden ist. Man kann natürlich nicht von jedem C++-Programmierer erwarten, dass er sich den Stroustrup ins Haus holt, aber besser wäre es. Der gute Mann – seines Zeichens Erfinder von C++ – schreibt sehr viel und eindringlich über sauberen, wiederverwendbaren Code.

Mit %n kannst du in die korrespondierende Integervariable schreiben, wieviele Elemente printf bislang bearbeitet hat:

Du liebe Güte - wo ist das denn her?

Aus der Dokumentation der printf()-Familie.

Das habe ich hier auch zum ersten Mal gelesen. Abgesehen davon ist mir absolut unklar, wozu das gut sein soll.

Vielleicht als Backdoor ;-)

Viele Grüße,
Robert