Byte* zu Hexstring



  • SeppJ schrieb:

    seb5594 schrieb:

    Das problem an der sache ist, das die Konsole sehr eingeschränkt ist was Libs angeht, ich kann natürlich standardfunctions with strlen, printf, va usw benutzen aber leider keine std libs (std::string/sstream usw).

    Das ist eine SEHR ungewöhnliche Einschränkung. Bist du sicher, dass du kein C machst? Kennt die Umgebung keine dynamische Speicherverwaltung?

    Und ja, sehr sicher. Das Sony SDK hat sehr schlecht detailierte Dokumentationen (teilweise japanisch) und bietet sehr viele Funktionen was die konsole direkt angeht, alles andere ist irgendwie auf der Strecke geblieben, was ich persöhnlich auch sehr merkwürdig finde. Die Konkurrenz (Microsoft) hat dagegen die nase vorne deutlich.
    Für die zwecke für die ich es benötige, reicht's eigentlich ausser die kleinen einschränkungen bei einigen dingen.

    Lg



  • Arcoth schrieb:

    Besser:

    void hexString(unsigned char const* bytes, std::size_t bytesLength, char* dest)
    {
    	static char const lookup[] = "0123456789ABCDEF";
    
    	for (std::size_t i = 0; i != bytesLength; ++i)
    	{
    		dest[2*i  ] = lookup[ bytes[i] >> 4  ];
    		dest[2*i+1] = lookup[ bytes[i] & 0xF ];
    	}
    }
    

    Testprogramm:

    int main()
    {
    	unsigned char const arr[] = {1, 2, 3, 4, 5};
    	char dest[2*sizeof arr + 1];
    
    	hexString(arr, sizeof arr, dest);
    	dest[2*sizeof arr] = 0;
    
    	std::cout << dest;
    }
    

    Mit erwarteter Ausgabe. Die Nullterminierung sollte dem Aufrufer überlassen werden.

    Leider bekomme ich immer als ergebnis diesen char
    "0EDAAED9F480EA0CBF80D2C7EB2D8869� >X"


  • Mod

    Du setzt den Nullterminator zu spät.

    Schreib mal

    temp[32] = 0;
    

    hinter den Aufruf.



  • Arcoth schrieb:

    Die Nullterminierung sollte dem Aufrufer überlassen werden.

    Was für einen Zweck hat das? Premature optimization zu Lasten von Fehleranfälligkeit!?



  • Arcoth schrieb:

    Du setzt den Nullterminator zu spät.

    Schreib mal

    temp[32] = 0;
    

    hinter den Aufruf.

    Leider nein, so ist mein Funktionsaufruf

    char dest[0x21];
    	hexString(buffer, 0x10, dest);
    	dest[0x20] = 0;
    	return dest;
    


  • Arcoth schrieb:

    Die Nullterminierung sollte dem Aufrufer überlassen werden.

    Weil? Ohne Nullterminierung sollte deine Funktion nicht String im Namen haben ...



  • Swordfish schrieb:

    Arcoth schrieb:

    Die Nullterminierung sollte dem Aufrufer überlassen werden.

    Weil? Ohne Nullterminierung sollte deine Funktion nicht String im Namen haben ...

    Hab jetzt mal den char array von 0x21 auf 0x20 gemacht und das ist dann das resultut

    "0EDAAED9F480EA0C� >XD2C7EB2D8869"



  • selbercoden? schrieb:

    Achtung, du gibst da einen Zeiger auf ein lokales Array zurück. Nimm entweder malloc oder überlass die Bufferverwaltung dem Aufrufer.



  • selbercoden? schrieb:

    selbercoden? schrieb:

    Achtung, du gibst da einen Zeiger auf ein lokales Array zurück. Nimm entweder malloc oder überlass die Bufferverwaltung dem Aufrufer.

    Malloc fällt schonmal aus der auswahl durch, wie meinst mit überlassen der bufferverwaltung?

    Lg



  • Arcoth hat dir die Lösung doch eh schon gegeben ...

    #include <cstddef>
    #include <iostream>
    
    void bytes2hexstring( char * dst, char unsigned const * bytes, std::size_t num_bytes )
    {
    	char const * lookup{ "0123456789ABCDEF" };
    
    	for( std::size_t i{}; i < num_bytes; ++i ) {
    
    		dst[ 2 * i     ] = lookup[ bytes[ i ] >> 4   ];
    		dst[ 2 * i + 1 ] = lookup[ bytes[ i ] & 0x0f ];
    	}
    
    	dst[ 2 * num_bytes ] = '\0';
    }
    
    int main()
    {
    	char unsigned hash[] =
    		{ 0x0E, 0xDA, 0xAE, 0xD9, 0xF4, 0x80, 0xEA, 0x0C,
    		  0xBF, 0x80, 0xD2, 0xC7, 0xEB, 0x2D, 0x88, 0x69 };
    
    	char buffer[ sizeof hash * 2 + 1 ];  // Puffer wird vom Aufrufer zur Verfuegung gestellt.
    
    	bytes2hexstring( buffer, hash, sizeof hash );
    
    	std::cout << buffer << '\n';
    }
    


  • Swordfish schrieb:

    Arcoth hat dir die Lösung doch eh schon gegeben ...

    #include <cstddef>
    #include <iostream>
    
    void bytes2hexstring( char * dst, char unsigned const * bytes, std::size_t num_bytes )
    {
    	char const * lookup{ "0123456789ABCDEF" };
     
    	for( std::size_t i{}; i < num_bytes; ++i ) {
    
    		dst[ 2 * i     ] = lookup[ bytes[ i ] >> 4   ];
    		dst[ 2 * i + 1 ] = lookup[ bytes[ i ] & 0x0f ];
    	}
    
    	dst[ 2 * num_bytes ] = '\0';
    }
    
    int main()
    {
    	char unsigned hash[] =
    		{ 0x0E, 0xDA, 0xAE, 0xD9, 0xF4, 0x80, 0xEA, 0x0C,
    		  0xBF, 0x80, 0xD2, 0xC7, 0xEB, 0x2D, 0x88, 0x69 };
    
    	char buffer[ sizeof hash * 2 + 1 ];  // Puffer wird vom Aufrufer zur Verfuegung gestellt.
    
    	bytes2hexstring( buffer, hash, sizeof hash );
    
    	std::cout << buffer << '\n';
    }
    

    Dennoch stimmt das endergebnis nicht wirklich

    void hexString(unsigned char *bytes, size_t bytesLength, char *dest)
    {
    	char const lookup[] = "0123456789ABCDEF";
    	for (std::size_t i = 0; i != bytesLength; ++i)
    	{
    		dest[2 * i] = lookup[bytes[i] >> 4];
    		dest[2 * i + 1] = lookup[bytes[i] & 0xF];
    	}
    	dest[2 * bytesLength] = '\0';
    }
    

    So rufe ich die Funktion

    char dest[sizeof buffer * 2 + 1];
    	hexString(buffer, sizeof buffer, dest);
    	return dest;
    

    Mein Buffer ist 16 bytes groß (0x10)

    Ergebnis:
    "0EDAAED9F480EA0CBF80D2C7EB2D8869� >X"
    Richtig wäre
    "0EDAAED9F480EA0CBF80D2C7EB2D8869"

    Lg



  • char dest[sizeof buffer * 2 + 1]; 
        hexString(buffer, sizeof buffer, dest); 
        return dest;
    

    Du returnst schon wieder etwas aus dem lokalen Namensraum...



  • seb5594 schrieb:

    So rufe ich die Funktion

    char dest[sizeof buffer * 2 + 1];
    	hexString(buffer, sizeof buffer, dest);
    	return dest;  // <<-- hier!!
    

    In welcher Funktion steht denn das? Wo wird deren Ergebnis ausgegeben?
    Ist dir klar, dass du schon wieder eine Funktionslokale Variable zurückgibst?



  • selbercoden? schrieb:

    selbercoden? schrieb:

    Achtung, du gibst da einen Zeiger auf ein lokales Array zurück. Nimm entweder malloc oder überlass die Bufferverwaltung dem Aufrufer.



  • Swordfish schrieb:

    seb5594 schrieb:

    So rufe ich die Funktion

    char dest[sizeof buffer * 2 + 1];
    	hexString(buffer, sizeof buffer, dest);
    	return dest;  // <<-- hier!!
    

    In welcher Funktion steht denn das? Wo wird deren Ergebnis ausgegeben?
    Ist dir klar, dass du schon wieder eine Funktionslokale Variable zurückgibst?

    Ihr könntet mir auch sagen wie ich es sonst zurück geben sollte.
    Das ist meine MD5Hash Funktion...

    const char* HashMD5String(const char* String)
    {
    	uint8_t buffer[16];
    	if (cellMd5Digest(String, strlen(String), buffer) == CELL_OK)
    	{
    		char dest[sizeof buffer * 2 + 1];
    		hexString(buffer, sizeof buffer, dest);
    		return dest;
    	}
    	return "INVALID";
    }
    

    Danke schonmal 🙂



  • Das wurde schon gefühlte 20 mal gesagt, wenn du das immernoch nicht verstehst wird es mal langsam Zeit C/C++ zu lernen.



  • selbercoden? schrieb:

    selbercoden? schrieb:

    selbercoden? schrieb:

    Achtung, du gibst da einen Zeiger auf ein lokales Array zurück. Nimm entweder malloc oder überlass die Bufferverwaltung dem Aufrufer.



  • tkausl schrieb:

    Das wurde schon gefühlte 20 mal gesagt, wenn du das immernoch nicht verstehst wird es mal langsam Zeit C/C++ zu lernen.

    Tut mir leid das ich mich in einem C++ Forum angemeldet habe falls ich ein problem habe, man könnte auch einfach die Lösung geben oder?

    selbercoden? schrieb:

    selbercoden? schrieb:

    selbercoden? schrieb:

    selbercoden? schrieb:

    Achtung, du gibst da einen Zeiger auf ein lokales Array zurück. Nimm entweder malloc oder überlass die Bufferverwaltung dem Aufrufer.

    Du musst dich nich 100x selbst zitieren, die antwort wäre mir lieber.
    War leider mit solch einem problem bisher nie in konflikt.

    Lg

    Edit: per printf direkt in der funktion kommt der korrekt hash, wie returne ich es aber richtig nun?



  • seb5594 schrieb:

    [...] wie returne ich es aber richtig nun?

    Garnicht. Du übergibst deiner Funktion HashMD5String() zusätzlich ein 33 chars großes Array, in das HashMD5String() schreiben soll.



  • Du kannst in C oder C++ kein Array zurückgeben sondern nur einen Pointer darauf.

    Betrachte zum Beispiel folgenden Code:

    int *foo()
    {
        int arr[10];
        /* do some work */
        return arr;
    }
    

    Das Array arr ist im automatischen Speicher, d.h. es wird gelöscht wenn die Funktion foo() verlassen wird. Mit return arr gibst du einen Pointer auf arr zurück, nicht das Array selber. Das heisst du hast dann einen Pointer auf eine gelöschtes Array was natürlich ein Bug ist.

    Eine mögliche Lösung ist dass du das Array nicht selber lokal in der Funktion erzeugst sondern dass der Aufrufer das Array als Argument übergibt:

    void foo(int *arr)
    {
        /* do some work */
    }
    

    Eine andere Möglichkeit ist das Array mit malloc zu allozieren (würde ich in diesem Fall allerdings nicht machen).


Anmelden zum Antworten