Fragen zu 128-Bit Integer



  • @seldon: Hab großen Dank. Kannte ich so noch gar nicht. Ist aber im Nachhinein leicht verständlich.

    Habs soweit jetzt hinbekommen. Hier ein Bsp.-Prog. für std::cout:
    INTS128.cpp:

    #include <climits>
    #include <cstdint>
    #include <cinttypes>
    #include <cfloat>
    #include <cmath>
    #include <cstdlib>
    #include <cstdio>
    #include <stdio.h>
    #include <iostream>
    
    using namespace std;
    
    std::ostream &operator<<(std::ostream &out, __uint128_t x)
    {
      if(x >= 10)
      {
        out << x / 10;
      }
      return out << static_cast<unsigned>(x % 10);
    }
    
    std::ostream &operator<<(std::ostream &out, __int128_t x)
    {
      if(x < 0)
      {
        out << '-';
        x = -x;
      }
      return out << static_cast<__uint128_t>( x);
    }
    
    int main(int argc, char *argv[])
    {
      __int128_t         Var31 = 0, tmp31 = 0;
      __uint128_t        Var32 = 0, tmp32 = 1;
    
      cout << "128-Bit Integer\n-----------------\n";
    
      __int128_t INT128_MIN = (-170141183460469231731.687303715884105728) * pow(10,18);
      __int128_t INT128_MAX = ( 170141183460469231731.687303715884105727) * pow(10,18);
    
      //cout << "Vermutet:\nINT128-MIN:" << INT128_MIN << "\nINT128-MAX: " << INT128_MAX << "\n\nBerechnet:\n";
    
      __int128_t TMP128 = 0;
      TMP128 = INT128_MAX + 1;                       // ergibt INT128-MIN
      cout << "INT128-MIN: " << TMP128 << "\n";      // Ausgabe von INT128-MIN
      TMP128 = INT128_MIN - 1;                       // ergibt INT128-MAX
      cout << "INT128-MAX:  " << TMP128 << "\n";     // Ausgabe von INT128-MAX
    
      __uint128_t UINT128_MAX = (340282366920938463463.374607431768211455) * pow(10,18);
      __uint128_t UINT128_MIN = 0/* * pow(10,18)*/;
    
      __uint128_t TMPu128 = 0;
      TMPu128 = UINT128_MAX + 1;                     // ergibt UINT128-MIN
      cout << "UINT128-MIN: " << TMPu128 << "\n";    // Ausgabe von UINT128-MIN
      TMPu128 = UINT128_MIN - 1;                     // ergibt UINT128-MAX
      cout << "UINT128-MAX: " << TMPu128 << "\n";    // Ausgabe von UINT128-MAX
    
      getchar();
      return 0;
    }
    

    OS: Linux x64-86 (bei mir Scientific Linux 6.1 x64 (up2date))

    g++(GCC)-Version:
    g++ (GCC) 4.4.5 20110214 (Red Hat 4.4.5-6)

    Glibc: x86_x64 - v2.12-1.25.el6_1.3

    Compile (release):
    g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s source.cpp -o dest

    Output (exec):

    128-Bit Integer
    -----------------
    INT128-MIN: -170141183460469231731687303715884105728
    INT128-MAX:  170141183460469231731687303715884105727
    UINT128-MIN: 0
    UINT128-MAX: 340282366920938463463374607431768211455
    

    -----------------------
    @seldo, wüsstest Du noch oder jemand anderes, wie man auch printf(,) dies beibringen kann?

    Und kann man und wenn ja wie, printf(,) weitere Makros beibringen?

    Ich wüsste da zwar jetzt ne Möglichkeit einfach einen Output mittels std:cout in eine String- bzw. char[]-Variable zu stecken und diese fprint(,) zu übergeben, allerdings würde ich nur ungern printf(,) mit std::cout kreuzen wollen. Lieber wäre mir, wenn ich wahlweise mein überladenes std::cout oder printf(,) verwenden könnte, ohne dass das eine vom anderen abhängig ist.

    THX im Voraus,

    Grüße

    Schlitzauge 🙂



  • Die Lösung ist, printf einfach nicht zu verwenden. Wenn du unbedingt eine printf-artige Funktion willst, dann bastel dir einen Wrapper um std::cout. Da du GCC verwendest, ist das mit Variadic Templates sehr einfach.



  • eine moeglichkeit waere:

    const char* prn_int(int x)
    {
       static const int size = 20;
       static char buf[size];
       char *p = buf + size - 1;
       *p = '\0';
       --p;
       bool sign = false;
    
       if(x == 0)
       {
          *p = '0';
          return p;
       }
    
       if(x < 0)
       {
          sign = true;
          x *= -1;
       }
    
       while(x > 0)
       {
          if(x < 10)
          {
             *p = '0' + static_cast<char>(x);
             x = 0;
          }
          else
          {
             *p = '0' + static_cast<char>(x % 10);
             x /= 10;
          }
    
          --p;
       }
    
       if(sign == true)
          *p = '-';
       else
          ++p;
    
       return p;
    }
    
    int main()
    {
       printf("test %s", prn_int(0));
    }
    

    ich hab hier in dem beispiel anstatt deinem int128 nen normalen int genommen. musst natuerlich dann anpassen.

    Meep Meep


  • Mod

    Meep Meep schrieb:

    eine moeglichkeit waere:

    Die ist dann allerdings nicht reentrant,

    printf("test %s %s", prn_int(0), prn_int(1));
    

    geht so schon mal nicht.



  • na dann macht man buffer halt thread local.

    sollte ja nur als beispiel dienen.

    Meep Meep



  • Wieso nicht einfach stringstreams mit der oben genannten Funktion benutzen und so Sachen wie c_str() nutzen.



  • Die Lösung ist, printf einfach nicht zu verwenden. Wenn du unbedingt eine printf-artige Funktion willst, dann bastel dir einen Wrapper um std::cout. Da du GCC verwendest, ist das mit Variadic Templates sehr einfach.

    Wie würde das dann aussehen. Mit Templates hatte ich bisher noch nicht so viel zu tun.

    na dann macht man buffer halt thread local.

    Wie meinst Du das? Wie müsste dann Deine Funktion aussehen, dass sie Thread locale ist? Was muss da genau verändert werden?

    Wieso nicht einfach stringstreams mit der oben genannten Funktion benutzen und so Sachen wie c_str() nutzen.

    Natürlich. An sowas hab ich auch schon längst gedacht. Wie ich schon erwähnte, kann ich auch meine überladenen std::OStream<<-Operatoren nutzen und eine print-Funktion für die 128-Bit-INT-Typen schreiben, welche dann einfach als Parameter printf(,) übergeben wird/werden.

    Eine Ausgabe-Funktion zu schreiben, stellt kein Problem dar. Ich suche aus reiner Neugier eine Möglichkeit, die [U]INT128-Typen bzw. Variablen davon, direkt in printf(,) zu nutzen, so wie ich es jetzt schon mit std::cout kann.

    Für Typen wie "__int64_t" gibt es für printf(,) bereits Lösungen, in Form von [PRI-]Makros, oder wie auch immer man sowas nennt, Bsp.:

    __int64_t Variable = 1024;
    printf("x: %"PRIi64"\n",Variable)";
    

    Es wäre toll, wenn es auch PRId128, PRIi128 oder PRIu128 geben würde.
    In der Doku zu meinem Compiler oder den Bibliotheken oder im I-net kann ich leider dazu nichts finden. Zumindest sehe ich es nicht, wenn es denn etwas Derartiges gibt. Wenn jemand was finden sollte, bitte posten. Vlt. heißen die PRI-Makro´s für die 128-Bit INT-Typen einfach nur anders.

    Oder kann man eigene PRI-Makro´s schreiben und diese dann einfach in printf(,) verwenden? Oder könnte man printf(,) auch einfach überladen?

    Der Grund, weshalb ich nicht einfach auf reine C++-Lösungen, wie die der std::[O]Streams oder Stringstreams ausweiche, ist der, dass ich hin und wieder leider nur reines C verwenden muss bzw. möchte. Lösungen mit C++-Elementen hab ich schon (teils Eigenrecherchen und Experimente, teils tatkräftiger Hilfen Eurerseits [HABT GROßEN DANK!]). Insb. was Threadsicherheit angeht, was ich insb. beim Einsatz von OpenMP benötige, würde ich lieber auf printf(,), anstatt auf std:cout setzen. Ich krieg zwar mit beiden Methoden ne Ausgabe hin, bei std::cout ist aber mehr Arbeit von Nöten und zieht alles nur unnötig in die Länge, auch wenns, wie ich finde, deutlich komfortabler ist, aber das ist ja bekanntlich Geschmackssache. Ebenso möchte ich nicht immer C-Style mit C++-Style mixen wollen.

    Idialerweise peile ich folgendes Ziel an (wenn es denn möglich wäre^^):

    __int128_t Variable128 = 1024;
    printf("x: %"PRIi128"\n",Variable128);
    // oder meinetwegen auch mit anderen "Platzhaltern"
    printf("x: %"IRGENDWAS"\n",Variable128);
    

    Ziel sollte es sein, in printf(,) die Variablen einfach direkt zu übergeben, nicht über Funktionen. Wenn natürlich nichts anderes geht, hab ich auch kein Problem damit, auf Funktionen zu setzen oder gleich mit C++-Methoden (std::Ostream, Stringstream, etc.) zu arbeiten. Es ist ja jetzt auch kein absolutes MustHave, sondern reine Neugier, wie man printf(,) zum Kooperieren bringen könnte.

    Abgesehen vom Hauptthema: 128-Bit-Integer. Seit C++ kann man Operatoren super leicht überladen, siehe Bsp. std:Ostream<< (oben). Nun kann man mit struct und class, auch eigene Datentypen schreiben, z.B. BRÜCHE. Mit dem Überladen von std::Ostream<< (std::cout) kann ich so einfach auch eigene Datentypen mit std::cout verwenden. Wie aber hat man das damals bzw. noch Heute in C gemacht?
    U.a. ist die C-Standard-Ausgabe-Funktion bekanntlich printf(,) für sowas. Darum meine Neugier und Nachfrage.

    Ich suche jetzt schon seit Tagen, finde aber nichts Richtiges.

    Grüße

    Schlitzauge 🙂



  • void myprintf(char const* format)
    {
        std::cout << format;
    }
    
    template <typename Head, typename... Tail>
    void myprintf(char const* format, Head&& head, Tail&&... tail)
    {
        while(*str != '%')
            std::cout << *str++;
    
        std::cout << head;
    
        printf(++str, std::forward<Tail>(tail)...);
    }
    

    Und wenns noch threadsafe sein soll, dann bastel dir noch ne Wrapper-Funktion mit Mutex drumherum. Außerdem bezweifle ich mal, dass printf threadsafe ist.



  • Ich habe jetzt folgendes:

    INTS128_2.cpp

    #include <climits>
    #include <cstdint>
    #include <cinttypes>
    #include <cfloat>
    #include <cmath>
    #include <string>  //std:string
    #include <string.h>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <stdio.h>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <termios.h>
    
    using namespace std;
    
    // Möglichkeit 1 (für std::cout)
    std::ostream &operator<<(std::ostream &out, __uint128_t x)
    {
      if(x >= 10)
      {
        out << x / 10;
      }
      return out << static_cast<unsigned>(x % 10);
    }
    
    std::ostream &operator<<(std::ostream &out, __int128_t x)
    {
      if(x < 0)
      {
        out << '-';
        x = -x;
      }
      return out << static_cast<__uint128_t>( x);
    }
    
    // Möglichkeit 2 (für printf() mit C++-Elementen)
    const char* INT128ToCSTR(__int128_t x)
    {
      stringstream sstr;
      sstr<<x;
      return sstr.str().c_str();
    }
    
    const char* UINT128ToCSTR(__uint128_t x)
    {
      stringstream sstr;
      sstr<<x;
      return sstr.str().c_str();
    }
    
    // Möglichkeit 3 (für printf() mit C-Elementen)
    const char* prn_int128(__int128_t x)
    {
      static const __int128_t size = 20;
      static char buf[size];
      char *p = buf + size - 1;
      *p = '\0';
      --p;
      bool sign = false;
    
      if(x == 0)
      {
        *p = '0';
        return p;
      }
      if(x < 0)
      {
        sign = true;
        x *= -1;
      }
    
      while(x > 0)
      {
        if(x < 10)
        {
          *p = '0' + static_cast<char>(x);
          x = 0;
        }
        else
        {
          *p = '0' + static_cast<char>(x % 10);
          x /= 10;
        }
        --p;
      }
    
      if(sign == true)
      {
        *p = '-';
      }
      else
      {
        ++p;
      }
      return p;
    }
    
    int main(int argc, char *argv[])
    {
      __int128_t         Var31 = 0, tmp31 = 0;
      __uint128_t        Var32 = 0, tmp32 = 1;
    
      cout << "128-Bit Integer\n=====================================================\n";
      cout << "\n+Mit std::cout:\n----------------------------------------------------\n";
    
      __int128_t INT128_MIN = (-170141183460469231731.687303715884105728) * pow(10,18);
      __int128_t INT128_MAX = ( 170141183460469231731.687303715884105727) * pow(10,18);
    
      //cout << "Vermutet:\nINT128-MIN:" << INT128_MIN << "\nINT128-MAX: " << INT128_MAX << "\n\nBerechnet:\n";
    
      __int128_t TMP128 = 0;
      TMP128 = INT128_MAX + 1;                       // ergibt INT128-MIN
      cout << "INT128-MIN: " << TMP128 << "\n";      // Ausgabe von INT128-MIN
      TMP128 = INT128_MIN - 1;                       // ergibt INT128-MAX
      cout << "INT128-MAX:  " << TMP128 << "\n";     // Ausgabe von INT128-MAX
    
      __uint128_t UINT128_MAX = (340282366920938463463.374607431768211455) * pow(10,18);
      __uint128_t UINT128_MIN = 0/* * pow(10,18)*/;
    
      __uint128_t TMPu128 = 0;
      TMPu128 = UINT128_MAX + 1;                     // ergibt UINT128-MIN
      cout << "UINT128-MIN: " << TMPu128 << "\n";    // Ausgabe von UINT128-MIN
      TMPu128 = UINT128_MIN - 1;                     // ergibt UINT128-MAX
      cout << "UINT128-MAX: " << TMPu128 << "\n";    // Ausgabe von UINT128-MAX
    
      cout << "\n+Mit printf(,) UND prn_int128():\n----------------------------------------------------\n";
      printf("x: %s\n",prn_int128(1024));                          //geht
      printf("x: %s, y: %s\n",prn_int128(2048),prn_int128(4096));  //geht nicht
    
      cout << "\n+Mit printf(,) UND [U]INT128ToCSTR(): (EINZELN)\n----------------------------------------------------\n";
      printf("INT128-MIN: %s\n",INT128ToCSTR(INT128_MIN));      //geht
      printf("INT128-MAX:  %s\n",INT128ToCSTR(INT128_MAX));     //geht
      printf("UINT128-MIN: %s\n",UINT128ToCSTR(UINT128_MIN));   //geht
      printf("UINT128-MAX: %s\n",UINT128ToCSTR(UINT128_MAX));   //geht
    
      cout << "\n+Mit printf(,) UND [U]INT128ToCSTR(): (ZUSAMMEN)\n----------------------------------------------------\n";
      //geht nicht
      printf("INT128-MIN:%s\nINT128-MAX:%s\nUINT128-MIN:%s\nUINT128-MAX:%s\n",INT128ToCSTR(INT128_MIN),INT128ToCSTR(INT128_MAX),UINT128ToCSTR(UINT128_MIN),UINT128ToCSTR(UINT128_MAX));
    
      getchar();
      return 0;
    }
    

    Output (Exec):

    128-Bit Integer
    =====================================================
    
    +Mit std::cout:
    ----------------------------------------------------
    INT128-MIN: -170141183460469231731687303715884105728
    INT128-MAX:  170141183460469231731687303715884105727
    UINT128-MIN: 0
    UINT128-MAX: 340282366920938463463374607431768211455
    
    +Mit printf(,) UND prn_int128():
    ----------------------------------------------------
    x: 1024
    x: 2048, y: 2048
    
    +Mit printf(,) UND [U]INT128ToCSTR(): (EINZELN)
    ----------------------------------------------------
    INT128-MIN: -170141183460469231731687303715884105728
    INT128-MAX:  170141183460469231731687303715884105727
    UINT128-MIN: 0
    UINT128-MAX: 340282366920938463463374607431768211455
    
    +Mit printf(,) UND [U]INT128ToCSTR(): (ZUSAMMEN)
    ----------------------------------------------------
    INT128-MIN:-170141183460469231731687303715884105728
    INT128-MAX:-170141183460469231731687303715884105728
    UINT128-MIN:0
    UINT128-MAX:-170141183460469231731687303715884105728
    

    ------------------------------
    Wie schon Letztens erwähnt, funktioniert das Arbeiten mit std::cout Ostream<< und damit auch mit stringstream´s.
    Dennoch hab ich noch eine Frage / ein Problem mit folgenden printf()-Alternativen:

    Camper schrieb:

    Meep Meep schrieb:
    eine moeglichkeit waere:

    Die ist dann allerdings nicht reentrant,

    printf("test %s %s", prn_int(0), prn_int(1));
    

    geht so schon mal nicht.
    Meep Meep antwortete:

    na dann macht man buffer halt thread local.
    sollte ja nur als beispiel dienen.

    Das Bezieht sich auf die prn_int128(__int128_t)-Funktion.
    Wie beim Output zu sehen ("+Mit printf(,) UND prn_int128():"), stimmt das natürlich.

    Gleiches bzw. ähnliches Problem scheint auch bei meinen zwei neuen Funktionen INT128ToCSTR() und UINT128ToCSTR() vorhanden zu sein, wie der Output ("+Mit printf(,) UND [U]INT128ToCSTR(): (ZUSAMMEN))" zeigt. Also zumindest in Kombination mit printf().

    Was heißt eigentlich eine Variable "thread local" zu machen? Im Moment arbeite ich ohne irgendwelche Parallelisierungstechniken a´la OpenMP. Also reine Single-Thread/-Prozess-Programmierung. Gleichwohl benötige ich später natürlich Threadsicherheit, aber das mal jetzt außen vor.

    Wie müssten denn die Funktionen prn_int128(__int128_t), INT128ToCSTR(), sowie UINT128ToCSTR() aussehen, damit die Ausgaben wieder stimmen, wenn man diese Funktionen bei printf(,) mehrfach als Parameter übergeben möchte?



  • Einfach das static weg? Wie kommt man überhaupt auf die blöde Idee, da ein static hinzumachen? Das habe ich mich schon so oft bei so manchen C-Programmierern gefragt.



  • // Möglichkeit 2 (für printf() mit C++-Elementen)
    const char* INT128ToCSTR(__int128_t x)
    {
      stringstream sstr;
      sstr<<x;
      return sstr.str().c_str();
    }
    
    const char* UINT128ToCSTR(__uint128_t x)
    {
      stringstream sstr;
      sstr<<x;
      return sstr.str().c_str();
    }
    

    Falsch, undefiniertes Verhalten, der stringstream gibt den Speicher für den String im Destruktor frei.



  • 314159265358979 schrieb:

    Einfach das static weg? Wie kommt man überhaupt auf die blöde Idee, da ein static hinzumachen? Das habe ich mich schon so oft bei so manchen C-Programmierern gefragt.

    Hm, klingt logisch. OK, bringt aber keinen Erfolg?:

    const char* prn_int128(__int128_t x)
    {
      const __int128_t size = 20;
      char buf[size];
      char *p = buf + size - 1;
      *p = '\0';
      --p;
      bool sign = false;
    
      if(x == 0)
      {
        *p = '0';
        return p;
      }
      if(x < 0)
      {
        sign = true;
        x *= -1;
      }
    
      while(x > 0)
      {
        if(x < 10)
        {
          *p = '0' + static_cast<char>(x);
          x = 0;
        }
        else
        {
          *p = '0' + static_cast<char>(x % 10);
          x /= 10;
        }
        --p;
      }
    
      if(sign == true)
      {
        *p = '-';
      }
      else
      {
        ++p;
      }
      return p;
    }
    

    Ethon schrieb:

    Falsch, undefiniertes Verhalten, der stringstream gibt den Speicher für den String im Destruktor frei.

    ??? Das versteh jetzt einer. Wenn ich die Funktionen mit printf(,) einzeln aufrufe (siehe Output: ""\n+Mit printf(,) UND [U]INT128ToCSTR(): (EINZELN)\n"), funktionierts doch. Was genau hast Du gemeint?



  • Schlitzauge schrieb:

    Hm, klingt logisch. OK, bringt aber keinen Erfolg?:

    Du darfst natürlich keinen Zeiger auf eine lokale Variable zurückgeben. Nimm einen out-Parameter. War ein denkfehler meinerseits. Sorry.

    Ethon schrieb:

    ??? Das versteh jetzt einer. Wenn ich die Funktionen mit printf(,) einzeln aufrufe (siehe Output: ""\n+Mit printf(,) UND [U]INT128ToCSTR(): (EINZELN)\n"), funktionierts doch. Was genau hast Du gemeint?

    Der stringstream hat sich Speicher angefordert. Wenn der Scope verlassen wird, wird der Speicher freigegeben. Auch hier musst du einen out-Parameter nehmen. (Oder C-Strings komplett lassen.)

    P.S.: Warum schreibst du eigentlich immer "printf(,)", also wozu da der ','?



  • Schlitzauge schrieb:

    Ethon schrieb:

    Falsch, undefiniertes Verhalten, der stringstream gibt den Speicher für den String im Destruktor frei.

    ??? Das versteh jetzt einer. Wenn [...] funktionierts doch. Was genau hast Du gemeint?

    Undefiniertes Verhalten bedeutet, dass es funktionieren kann, aber nicht muss. Wenn du Pech hast, passiert an einem anderen Ort im Programm was ganz Merkwürdiges -> dein Code ist verbuggt.

    Mach das undefinierte Verhalten weg.



  • ??? Das versteh jetzt einer. Wenn ich die Funktionen mit printf(,) einzeln aufrufe (siehe Output: ""\n+Mit printf(,) UND [U]INT128ToCSTR(): (EINZELN)\n"), funktionierts doch. Was genau hast Du gemeint?

    So wäre es zb korrekt:

    // Möglichkeit 2 (für printf() mit C++-Elementen)
    string INT128ToSTR(__int128_t x)
    {
      stringstream sstr;
      sstr<<x;
      return sstr.str();
    }
    string UINT128ToSTR(__uint128_t x)
    {
      stringstream sstr;
      sstr<<x;
      return sstr.str();
    } 
    
    ................
    
    printf("%s", INT128ToSTR(123456789).c_str());
    


  • Ethon schrieb:

    So wäre es zb korrekt:

    JA ok, aber dabei ist der Rückgabetyp "string". Ich wollte gerne aber ohne string auskommen, sondern auf Standard-C-String (char[]) setzen, welcher anschließend von den zwei Funktionen jeweils zurückgegeben wird.
    Ich wollte das Konvertieren von stringstream nach c_str() gerne inline in der Funktion ausführen lassen, sodass ich auch wirklich nur C-Strings (char[]) zurückgebe und ich einfach nur die Funktionen in printf() verwenden kann, ohne sonstiges wie ".c_str()".



  • Das kannst du nicht, da du für char* Speicher anfordern müsstest, den du bei der direkten Übergabe an printf() nicht mehr freigeben kannst.

    Und sonst verwendest du eben nicht printf() ...



  • char const* int128_to_cstr(__int128_t x, char* buffer, std::size_t bufflen)
    {
      stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer, bufflen - 1, 0)] = 0;
      return buffer;
    }
    

    Die einzig haltwegs sinnvolle Möglichkeit die mir noch einfallen würde.

    char buffer[32];
    printf("%s", int128_to_cstr(123456789, buffer, 32));
    


  • Klick. Stimmt ja. Übergabe als Zeigerparameter.

    Hm. Nagut, macht den Code aber ziemlich hässlich.
    Ihr meint mit OUT-Parameter also sowas:

    char array[32];
    const char* Funktion(char* narray)
    {
      return narray;
    }
    

    ???
    Ich kannte OUT- und IN-Parameter bis dato nicht unter diesen Begriffen.

    Kann man die Bufferlänge nicht einfach via sizeof() inline in der Funktion anwenden?

    Machte es denn einen Unterschied ob / oder:

    const char*
    char const*
    

    ?



  • Schöner könntest du es natürlich mit STL-Containern machen. Aber dein ganzer Ansatz ist so C-ish, dass ich ihn auch so gelassen hab.

    char const* int128_to_cstr(__int128_t x, std::vector<char>& buffer)
    {
      stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer, buffer.size() - 1, 0)] = 0;
      return &buffer[0];
    }
    

    bzw

    template<std::size_t BuffSize>
    char const* int128_to_cstr(__int128_t x, std::array<char, BuffSize>& buffer)
    {
      stringstream sstr;
      sstr<<x;
      buffer[sstr.str().copy(buffer, buffer.size() - 1, 0)] = 0;
      return &buffer[0];
    }
    

    Wären die C++-igeren Methoden, die beide ohne Längen-Parameter auskommen würden ... aber Schwachsinn, der C++-Weg wäre es, nen std::string zurückzugeben.

    Kann man die Bufferlänge nicht einfach via sizeof() inline in der Funktion anwenden?

    Nope, in der Funktion existiert nur noch ein Pointer auf die Daten des Arrays (Syntax-Nazis, bittet diskutiert den Punkt jetzt nicht). Und ein Pointer ist für gewöhnlich 4/8 Byte groß.

    Machte es denn einen Unterschied ob / oder:

    Nöp, finde es nur logischer. Man liest ja von rechts nach links und 'const char*' liest sich als 'Pointer auf ein char, das konstant ist' während 'char const*' sich als 'Pointer auf ein konstantes char' liest.


Anmelden zum Antworten