C++ ist machmal echt seltsam



  • Gast3 schrieb:

    aber wer soll den entscheiden das dein "ABC..."-String erst in einen std::string konvertiert werden muss, x kann es nicht

    Natürlich ist es technisch nicht möglich, das so zu realisieren. Um das zu wissen braucht man aber schon recht genaues Detailwissen darüber, wie das ausgewertet wird.

    Gast3 schrieb:

    aber ich geben dir recht das es leicht zu Fehlern führt - und man denkt zu schnell das da alles automatisch konvertiert wird

    Das nicht alles automatisch konvertiert wird ist das eine, das hat man ja hin und wieder schon mal, das andere ist aber, dass es trotzdem kompiliert.

    Wenn man z.B. schreibt

    string x ="ABC" + "DEF"
    

    ;
    Bekommt man zumindest einen Fehler. Das Problem hier ist, das C++ an dieser Stelle die schwache Typisierung von C geerbt hat, die es erlaubt, das Typen implizit in andere Typen mit völlig unterschiedlicher Semantik umgewandelt werden. Das kann hoch gefährlich sein. Daran lässt sich aber wohl nichts mehr ändern. Vielen C-Altlasten kann man gut aus dem weg gehen indem man sie einfach nicht benutzt. An der Doppelbedeutung von char* und char sowie dem Pointer-Decay kommt aber niemand drum rum.



  • Man könnte eventuell auch argumentieren, dass die Operator+ Überladung für std::string ein Fehler war, da sie diesem Operator kontextabhängig eine unterschiedliche Bedeutung gibt. Ein noch größerer Fehler war es wahrscheinlich, diesen Operator auch noch gemischt für char* und char zu überladen, was fälschlicherweise suggeriert man könne std::strings mit C-Strings und Literalkonstanten in solchen Ausdrücken beliebig mischen..



  • Gerade Bjarne Stroustrup will ja gerne den Eindruck erwecken, man könne insbesondere seit C++14 aus C++ eine konsistente, sichere und dennoch vergleichsweise einfach zu erlernende Sprache machen, indem man nur noch eine ideomatische Teilmenge der Sprache lehrt, weil die ganzen unsicheren und fehleranfälligen Low-Level Sachen bräuchten ja eh nur die Library-Implementierer zu verstehen. Ich fürchte jedoch das ist unmöglich, gerade wegen solchen Dingen.



  • TNA schrieb:

    kompiliert ohne Warnung, passiert alle statischen Codanalys Tests

    Clang gibt tatsächlich eine nette Warnung:

    test.cpp:7:42: warning: adding 'char' to a string pointer does not append to the string [-Wstring-plus-char]
      result += "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + '\n';
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
    test.cpp:7:42: note: use array indexing to silence this warning
      result += "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + '\n';
                                             ^
                &                            [     ]
    

    Die Lösung für dieses Problem wäre in C++14 wohl so (Man beachte das 's' Suffix):

    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"s + '\n';
    


  • Was macht das s Suffix, Stichwort ?



  • c14_new schrieb:

    Was macht das s Suffix, Stichwort ?

    Es konvertiert den Ausdruck in einen std::string.



  • sebi707 schrieb:

    Clang gibt tatsächlich eine nette Warnung:

    Das ist ne tolle Sache. GCC macht das leider nicht.



  • TNA schrieb:

    Trotz mittlerweile doch recht langer Erfahrung stolpere ich…

    Danke. Den Code kriegen gleich mal die nächsten Bewerber zu sehen. 😃



  • TNA schrieb:

    Gerade Bjarne Stroustrup will ja gerne den Eindruck erwecken, man könne insbesondere seit C++14 aus C++ eine konsistente, sichere und dennoch vergleichsweise einfach zu erlernende Sprache machen, indem man nur noch eine ideomatische Teilmenge der Sprache lehrt, weil die ganzen unsicheren und fehleranfälligen Low-Level Sachen bräuchten ja eh nur die Library-Implementierer zu verstehen. Ich fürchte jedoch das ist unmöglich, gerade wegen solchen Dingen.

    In diese Richtung wurde in der letzten auch ganz gute Arbeit gemacht.
    Allerdings kollidiert der Anspruch der "einfachen Sprache" wie im vorliegenden Fall oft mit dem gleichzitigen Anspruch, dass sich 20 Jahre alter Code immer noch mit aktuellen Compilern bauen lassen soll.

    Ich würde es auch als intuitiver empfinden, wenn "abc" von Haus aus ein String-Literal wäre, anstatt eine Aneinanderreihung von Bytes irgendwo im Speicher.
    In einer modernen Sprache sollte ersteres der Standardfall sein (ist auch sicherlich das, was man in neuem Code am häufigsten braucht) und letzteres der "Sonderfall",
    für den man dann eine etwas andere Syntax verwendet. Was das jedoch alles an altem Code kaputt machen würde, kannst du dir sicher selbst ausmalen 🙂
    ... von den ganzen "String"-Klassen, die man neben std::string sonst noch so in freier Wildbahn antrifft, will ich erst gar nicht anfangen.

    Vielleicht ringt man sich ja mal dazu durch die "einfachere Sprache" per Compiler-Flag aktivierbar zu machen (so wie man es bei vielen Compilern schon für c++11 machen muss).
    "abc" wäre dann automatisch ein std::string -Literal, und wenn man einen const char* haben will, muss man es anders schreiben.
    Oder ein char wäre ein "Zeichen", das man nicht einfach so wie z.B. einen (u)int8_t auf einen Pointer aufaddieren kann.

    Finnegan



  • Finnegan schrieb:

    Vielleicht ringt man sich ja mal dazu durch die "einfachere Sprache" per Compiler-Flag aktivierbar zu machen (so wie man es bei vielen Compilern schon für c++11 machen muss).
    "abc" wäre dann automatisch ein std::string -Literal, und wenn man einen const char* haben will, muss man es anders schreiben.
    Oder ein char wäre ein "Zeichen", das man nicht einfach so wie z.B. einen (u)int8_t auf einen Pointer aufaddieren kann.

    Diese Idee finde ich gefährlich. Erinnert mich an Python 2 und 3 Chaos.
    Nein ich finde sie sogar furchtbar.

    EDIT: Außer vielleicht mit Makros an und abstellbar, aber selbst dann stiftet das eher mehr chaos.

    EDIT 2: Wenn ich schon ein Beitrag in diesem Thread habe lasse ich nochmal das hier liegen:

    char c = '\n'["ABCDEFGHIJKLMNOP"];
    


  • char c = '\n'["ZuKurz"];
    !!warning: array index 10 is past the end of the array (which contains 7 elements) [-Warray-bounds]
    

    wenigstens kann der clang in manchen Situation was komisches erkennen

    '\n' verhält sich hier irgendwie wie ein array aber auch wie ein Wert - oder?



  • Finnegan schrieb:

    Ich würde es auch als intuitiver empfinden, wenn "abc" von Haus aus ein String-Literal wäre, anstatt eine Aneinanderreihung von Bytes irgendwo im Speicher.
    In einer modernen Sprache sollte ersteres der Standardfall sein (ist auch sicherlich das, was man in neuem Code am häufigsten braucht) und letzteres der "Sonderfall",

    Das ist Java-Denke und macht die Sache NICHT einfacher, sondern komplizierter.
    "abc" sollte ein char[3] sein und array-to-pointer sollte nicht automagisch konvertiert werden.


  • Mod

    Gast3 schrieb:

    char c = '\n'["ZuKurz"];
    !!warning: array index 10 is past the end of the array (which contains 7 elements) [-Warray-bounds]
    

    wenigstens kann der clang in manchen Situation was komisches erkennen

    '\n' verhält sich hier irgendwie wie ein array aber auch wie ein Wert - oder?

    a[b] für den eingebauten Operator [] ist das gleiche wie *(a + b) . Da Addition eines Wertes zu einem Zeiger kommutativ ist, ist es egal, ob a oder b der Zeiger bzw. der Index ist.



  • hatte mich im Test blöd verschrieben - die Fehlermeldung schnell überlesen und gedacht das es für Char-Literale ein Spezialfall wäre (Oh Gott!) - ist aber zum Glück nicht so - Puh!

    char x = 10["0123456789"];
    

    also kannst du meine Frage einfach dauerhaft aus deinem Gedächtnis löschen



  • volkard schrieb:

    Finnegan schrieb:

    Ich würde es auch als intuitiver empfinden, wenn "abc" von Haus aus ein String-Literal wäre, anstatt eine Aneinanderreihung von Bytes irgendwo im Speicher.
    In einer modernen Sprache sollte ersteres der Standardfall sein (ist auch sicherlich das, was man in neuem Code am häufigsten braucht) und letzteres der "Sonderfall",

    Das ist Java-Denke und macht die Sache NICHT einfacher, sondern komplizierter.
    "abc" sollte ein char[3] sein und array-to-pointer sollte nicht automagisch konvertiert werden.

    Ich lasse mich ja gerne von Argumenten überzeugen, aber so kann ich genau so gut behaupten, dass das "C-Denke" ist.
    Ich habe mich nicht für igendwelche "automagischen" Konvertierungen ausgesprochen, sondern lediglich angeregt, dass in einem vereinfachten C++
    der Ausdruck "abc" ein String-Literal sein könnte, also implizit ein "abc"s .
    Einen char -Array kann ich so immer noch als const char[] a = { 'a', 'b', 'c' } definieren, wenn man es denn benötigt. Genau wie jedes andere Array auch.

    Gut möglich, dass das vielleicht einige Dinge komplizierter macht, ich habe das nicht bis ins letzte Detail durchdacht, trotzdem würde ich dafür gerne ein paar Argumente hören.
    Eine Sache, die mir da einfallen würde ist, dass ein String im Gegensatz zu einem char -Array in C++ kein "1st Class Citizen" (builtin) ist, sondern lediglich eine Klasse in einer Bibliothek (wenn auch der Standardbibliothek).
    Das ganze wäre sicherlich etwas konsistenter, wenn string ein builtin-Typ wäre (nicht so ganz blasphemisch, wenn man bedenkt, dass z.B. C99 mit komplexen Zahlen auch einen de facto zusammengesetzten Datentypen als builtin anbietet).

    Finnegan



  • Ich denke es ist etwas anderes std::string als builtin hinzuzufügen als komplexe Zahlen, bei denen braucht man ja nur einen Real- und Imaginärteil. std::string benutzt den Standard-Allocator und deswegen auch new. Diese müssten dann auch builtin sein, oder wie soll der std::string seinen Speicher bekommen? Im Freestanding Environment wird das zu einem Problem.



  • patrick246 schrieb:

    Ich denke es ist etwas anderes std::string als builtin hinzuzufügen als komplexe Zahlen, bei denen braucht man ja nur einen Real- und Imaginärteil. std::string benutzt den Standard-Allocator und deswegen auch new. Diese müssten dann auch builtin sein, oder wie soll der std::string seinen Speicher bekommen? Im Freestanding Environment wird das zu einem Problem.

    Ich denke man kann durchaus eine String-Klasse implementieren, die im Falle eines Freestanding Environment den benötigten Speicher auf dem Stack reserviert
    (selbst für dynamische Strings, z.B. über verkettete Stack-Speicherbereiche), das sollte also nicht unbedingt ein Showstopper sein.

    Dieser Argumentationspfad führt allerdings in eine andere Richtung (macht ein builtin-String Sinn?). Mein Argument war jedoch lediglich, dass wenn "abc" ein String-Literal ist,
    es eine "rundere" Sache wäre, wenn der String ein builtin ist. Schließlich ist das "abc" -Literal ein Sprachfeature, für das man keinerlei Bibliotheken (nichtmal die Std) benötigt.
    Machbar wäre ein builtin-String schon, aber es widerspricht wahrscheinlich der Philosophie des Standardkommitees, die Kernsprache möglichst schlank zu halten.
    Daher ist der nicht-existente builtin-string eher ein Argument dafür "abc" eben weiterhin als char-Array zu interpretieren, da dieses allein durch Elemente der Kernsprache dargestellt werden kann.

    Trotzdem empfinde ich ("Hallo" + "Welt").length() (ohne s-Suffix) durchaus als intuitiv und würde es in der "einfacheren Sprache", die irgendwann mal aus C++ herausgeschält wird, durchaus begrüßen.
    ... auch wenn hier einige schon die Holzpflöcke spitzen und den Knoblauch holen 😃

    Finnegan



  • Finnegan schrieb:

    Daher ist der nicht-existente builtin-string eher ein Argument dafür "abc" eben weiterhin als char-Array zu interpretieren, da dieses allein durch Elemente der Kernsprache dargestellt werden kann.

    Aber eigentlich ist das ja eh nicht für alle Features gegeben. Ein

    for (int i : my_int_array);
    

    vermischt ja auch irgendwie Kernsprache mit std lib, als macht so eine Trennung doch eigentlich nicht viel Sinn oder?


  • Mod

    happystudent schrieb:

    for (int i : my_int_array);
    

    vermischt ja auch irgendwie Kernsprache mit std lib, als macht so eine Trennung doch eigentlich nicht viel Sinn oder?

    Wo wird denn da etwas vermischt? Meinst du, weil der Namespace std bei der Suche nach begin/end potentiell mit einbezogen wird?



  • happystudent schrieb:

    Aber eigentlich ist das ja eh nicht für alle Features gegeben. Ein

    for (int i : my_int_array);
    

    vermischt ja auch irgendwie Kernsprache mit std lib, als macht so eine Trennung doch eigentlich nicht viel Sinn oder?

    Wenn ich die Laufzeitumgebung für embedded systems reimplemetieren mag, dann ist bei den scoped for loops der einzige impact, daß ich ein globales begin() und end() (also mit ugly stl naming style) anbieten muss, was auf hübsche getBegin() und getEnd() mapt. Das war schon alles. Kein Problem.

    typeinfo oder was der new wirft sind da schlimmer.


Anmelden zum Antworten