Unsigned char array to int



  • Hallo alle zusammen,

    ich möchte einen unsigned char array in einen int umwandeln. Leider habe ich bis jetzt noch keine Ahnung, wie ich das anstellen soll.
    Wenn es einen char array wäre, würde ich ja einfach atoi() benutzen, aber ich habe und brauche eine unsigned char array.

    Kann mir da jemand helfen?

    Mfg, Martek



  • martek schrieb:

    Wenn es einen char array wäre, würde ich ja einfach atoi() benutzen, aber ich habe und brauche eine unsigned char array.

    int i = atoi ((char*)dein_array);
    


  • Dabei kommt aber nicht das richtige Ergebnis raus. Oder an der Array selber ist etwas komisch.
    In der steht 0, 0, 0, 192. Und ich würde dann gerne 192 als int rausbekommen...


  • Mod

    martek schrieb:

    Dabei kommt aber nicht das richtige Ergebnis raus. Oder an der Array selber ist etwas komisch.
    In der steht 0, 0, 0, 192. Und ich würde dann gerne 192 als int rausbekommen...

    Dazu musst du rechnen:

    int wert = c_array[3]
             + c_array[2] * (UCHAR_MAX +1)
             + c_array[1] * (UCHAR_MAX +1) * (UCHAR_MAX +1)
             + c_array[0] * (UCHAR_MAX +1) * (UCHAR_MAX +1) * (UCHAR_MAX +1);
    

    edit: Schreibfehler im Programm verbessert.

    edit2: ⚠ Moment mal: Wenn du signed chars hättest, würdest du das gleiche Problem mit atoi lösen? 😕 Entweder habe ich falsch verstanden was du willst oder du solltest nochmal gucken, was atoi macht.

    edit3: Wenn du wissen willst, wie man auf die Rechnung kommt: Stellenwertsystem



  • Ich nehme an, du meinst jeweils (UCHAR_MAX + 1).

    Wie dem auch sei, wenn es sich um einen 32bit-Integer in MSB-Darstellung handelt, bietet sich dafür ntohl an. Unter kontemporären Unices befindet die sich in netinet/in.h, und Windows in winsock2.h. Beispiel:

    #include <netinet/in.h>
    #include <tr1/cstdint>
    #include <iostream>
    
    int main() {
      unsigned char p[] = { 1, 2, 3, 4 };
      std::tr1::uint32_t val = ntohl(*reinterpret_cast<uint32_t const *>(p));
    
      std::cout << val << std::endl;
    }
    

    Das ist jetzt für den GCC, unter Windows sollte es aber so ähnlich aussehen, dass man es mit #ifdef um die Headereinbindungen und einem typedef angleichen kann.

    Der Vorteil gegenüber selbstgebastelten Lösungen ist, dass der Compiler besser optimieren kann. Bei mir z.B. ist ntohl, wenn der Compiler optmiert, ein Makro, dass die Zahl an eine scheinbar seit i486 genau hierfür vorhandene CPU-Instruction durchreicht, und auf Big-Endian-Architekturen etwa braucht es gar nichts zu machen. Das ist im Zweifel schneller als alles, was man sich eben selbst aus dem Ärmel schütteln kann.



  • #include <cstdio>
    #include <cstring>
    unsigned int char_array_to_uint(const char* arr, std::size_t length, bool terminating_zero)
    {
       if(arr==NULL || length==0)
    	   return 0;
       unsigned char tmp[sizeof(unsigned int)] = {};
       unsigned int zahl;
       const unsigned int n = 1;
       if(*(char*)&n & 1) //endianness
       {
          for(unsigned int i = 0; i != sizeof(unsigned int) && i != length; ++i)
             tmp[i]=arr[i];
          unsigned int zahl;
          std::memcpy(&zahl, tmp, sizeof(unsigned int));
       }
       else
       {
          arr+=length;
    	  if(terminating_zero)
    	  {
    		  if(length==1)
    			  return 0;
    		  --arr;
    	  }
          for(unsigned int i = 0; i != sizeof(unsigned int) && i != length; ++i)
          {
             --arr;
             tmp[sizeof(unsigned int)-(1+i)]=*arr;
          }
    
          std::memcpy(&zahl, tmp, sizeof(unsigned int));
       }
       return zahl;
    }
    
    template<std::size_t length>
    unsigned int char_array_to_uint(const char (&arg)[length], bool terminating_zero)
    {
       const char* arr = arg;
       if(arr==NULL || length == 0)
    	   return 0;
       unsigned char tmp[sizeof(unsigned int)] = {};
       unsigned int zahl;
       const unsigned int n = 1;
       if(*(char*)&n & 1)
       {
          for(unsigned int i = 0; i != sizeof(unsigned int) && i != length; ++i)
             tmp[i]=arr[i];
          unsigned int zahl;
          std::memcpy(&zahl, tmp, sizeof(unsigned int));
       }
       else
       {
    	   arr+=length;
          if(terminating_zero)
    	  {
    		  if(length==1)
    			  return 0;
    		  --arr;
    	  }
          for(unsigned int i = 0; i != sizeof(unsigned int) && i != length; ++i)
          {
             --arr;
             tmp[sizeof(unsigned int)-(1+i)]=*arr;
          }
    
          std::memcpy(&zahl, tmp, sizeof(unsigned int));
       }
       return zahl;
    }
    

    Einschränkungen:
    -Nicht definiert für middle endian
    -Nicht definiert für signed int [sollte bei Zweierkomplement klappen]
    -Nicht definiert für char == signed char und array elemente < 0 (cast zu unsigned char wird implizit vorgenommen, kann probleme bei Einerkomplement geben)



  • *Okay, ich glaube ich habe mich etwas umständlich ausgedrückt. Ich erkläre es nochmal ausführlich:
    Ich lese aus einer Date 4 Bytes, die ich dann in einer unsigend char array speicher. In dieser Array steht jetzt 0, 0, 0, 192 als Dezimalwerte.
    Diese Werte möchte ich jetzt zu einem Integer umwandeln, damit ich damit weiterarbeiten kann.
    Das Beispiel mit "atoi" war mein Fehler, denn soweit ich weiß funktioniert atoi nur wenn in der Array auch chars drin stehen, und keine Dezimalwerte.

    Nur wie bekomme ich jetzt den Integer?*

    Edit: Ich habe mir gerade nochmal das Beispiel von SeppJ angeguckt und jetzt gehts aufeinmal. Keine Ahnung was ich grad falsch gemacht habe.

    Viele Dank, es funktioniert!



  • chars SIND Dezimalwerte!


  • Mod

    martek schrieb:

    *Okay, ich glaube ich habe mich etwas umständlich ausgedrückt. Ich erkläre es nochmal ausführlich:
    Ich lese aus einer Date 4 Bytes, die ich dann in einer unsigend char array speicher. In dieser Array steht jetzt 0, 0, 0, 192 als Dezimalwerte.
    Diese Werte möchte ich jetzt zu einem Integer umwandeln, damit ich damit weiterarbeiten kann.
    Das Beispiel mit "atoi" war mein Fehler, denn soweit ich weiß funktioniert atoi nur wenn in der Array auch chars drin stehen, und keine Dezimalwerte.

    Nur wie bekomme ich jetzt den Integer?*

    Edit: Ich habe mir gerade nochmal das Beispiel von SeppJ angeguckt und jetzt gehts aufeinmal. Keine Ahnung was ich grad falsch gemacht habe.

    Viele Dank, es funktioniert!

    ⚠ Pass aber auf! Wie seldon korrekt bemerkt hat, muss es (UCHAR_MAX + 1) heißen. Ich habe es inzwischen verbessert, aber als du dies schriebst, stand es noch falsch da.



  • Gut, das erklärt auch den Fehler, den ich bei größeren Arrays bekommen habe.
    Damit wäre das auch geklärt^^

    Nochmals danke 🙂


Log in to reply