Code Bitte Erklären!



  • Hallo,

    es wäre nett wenn ihr mir eben das hier erklären könntet:

    void IClientPacketHandler::Decrypt(char *&szData)
    {
    	for(unsigned int i = 0; i < strlen(szData); i++)
    	{
    		szData[i] = (char)((char)szData[i] ^ (char)0xC3);
    	}
    }
    

    Das da was Decrypted also leserlich gemacht wird weiss ich nur bitte die einzelnen abschnitte genau erklären, es wäre sehr nett.

    Lg



  • Hmm Interessant den Code habe ich auch und mich Interessiert auch was der Bedeuten soll 😉



  • Jedes Zeichen des Strings wird mit 0xC3 xor-verknüpft.



  • fdfdg schrieb:

    Jedes Zeichen des Strings wird mit 0xC3 xor-verknüpft.

    hmmm ich werde mir das mal anschauen.
    Könntest du eventuell den rest auch noch erklären?

    Lg


  • Mod

    Gast123456789 schrieb:

    Könntest du eventuell den rest auch noch erklären?

    Da ist kein Rest, das ist alles was passiert.



  • SeppJ schrieb:

    Gast123456789 schrieb:

    Könntest du eventuell den rest auch noch erklären?

    Da ist kein Rest, das ist alles was passiert.

    Gut, dachte da wäre mehr 😢

    Danke euch beiden.



  • Wie der Name der Funtkion vermuten lässt, wird hier ein Datenpacket entschlüsselt, das vorher vermutlich übertragen wurde. Allerdings ist eine XOR-Verschlüsslung binnen Sekunden geknackt. Deshalb frage ich mich, wer benutzt sowas und wo hast du das her?!



  • Selbst wenn man von der Sinnlosigkeit der Verschlüsselung absieht, kommen für so ein kurzes Codestück erstaunlich viele Fragwürdigkeiten vor.

    void IClientPacketHandler::Decrypt(char *&szData)
    

    Warum hier eine Referenz genommen wird, weiss niemand. Der Zeiger selbst wird jedenfalls nicht geändert. Und was soll dieses sz -Präfix?

    szData[i] = (char)((char)szData[i] ^ (char)0xC3);
    

    Etwas viele Casts, oder? Zumal sie alle unnötig sind. Man könnte ausserdem gleich operator^= verwenden.

    for(unsigned int i = 0; i < strlen(szData); i++)
    

    So zu iterieren führt zu quadratischer Laufzeit. Iteriere lieber gleich mit Zeigern und prüfe auf die Nullterminierung.

    Das könnte dann so aussehen:

    void IClientPacketHandler::Decrypt(char* dataPtr)
    {
        for (; *dataPtr != '\0'; ++dataPtr)
            *dataPtr ^= 0xC3;
    }
    


  • Warum ist denn

    for (; *dataPtr != '\0'; ++dataPtr)
    

    schneller als

    for(unsigned int i = 0; i < strlen(szData); i++)
    

    ?
    Weil jedesmal die Stringlänge berechnet wird? Wäre dann nicht

    int len = strlen(szData);
    for(unsigned int i = 0; i < len; ++i)
    

    die schnellste Variante?



  • Nexus schrieb:

    for(unsigned int i = 0; i < strlen(szData); i++)
    

    So zu iterieren führt zu quadratischer Laufzeit. Iteriere lieber gleich mit Zeigern und prüfe auf die Nullterminierung.

    Wie bitte?



  • this->that schrieb:

    Nexus schrieb:

    for(unsigned int i = 0; i < strlen(szData); i++)
    

    So zu iterieren führt zu quadratischer Laufzeit. Iteriere lieber gleich mit Zeigern und prüfe auf die Nullterminierung.

    Wie bitte?

    Was macht StrLen ?


  • Mod

    StellerFragen schrieb:

    Weil jedesmal die Stringlänge berechnet wird? Wäre dann nicht

    int len = strlen(szData);
    for(unsigned int i = 0; i < len; ++i)
    

    die schnellste Variante?

    Wozu erst einmal über den ganzen String iterieren um die Zeichen zu zählen und dann nochmal ums sie zu ver-xor-en, wenn man auch gleich nur einmal über alle Zeichen iterieren kann, sie dabei ver-xor-dern kann und beim letzten Zeichen aufhören kann?

    Das würde ungefähr doppelt so lange dauern.



  • Zeus schrieb:

    this->that schrieb:

    Nexus schrieb:

    for(unsigned int i = 0; i < strlen(szData); i++)
    

    So zu iterieren führt zu quadratischer Laufzeit. Iteriere lieber gleich mit Zeigern und prüfe auf die Nullterminierung.

    Wie bitte?

    Was macht StrLen ?

    Gute Compiler werden doch den Funktionsaufruf aus der Schleife rausziehen?



  • this->that schrieb:

    Gute Compiler werden doch den Funktionsaufruf aus der Schleife rausziehen?

    Zumindest könnten sie es, bei Funktionen aus der Std-Lib ist ja klar, welche pure sind und welche nicht.



  • this->that schrieb:

    Gute Compiler werden doch den Funktionsaufruf aus der Schleife rausziehen?

    Warum die Nicht-Optimierung riskieren statt gleich richtig zu programmieren? Ist ja nicht so, dass letzteres hier besonders anspruchsvoll wäre.



  • Nexus schrieb:

    this->that schrieb:

    Gute Compiler werden doch den Funktionsaufruf aus der Schleife rausziehen?

    Warum die Nicht-Optimierung riskieren statt gleich richtig zu programmieren? Ist ja nicht so, dass letzteres hier besonders anspruchsvoll wäre.

    Weil man dann Gefaehr laeuft unnoetigerweise unleserlichen/frickeligen Code zu schreiben.
    Ist genauso wie mit den Leuten die Rueckgabeparameter per non-const Referenz uebergeben, weil sie meinen das sei viel Effizienter als mit by value return. Ergibt haesslicheren Code, obwohl jeder Compiler dank (N)RVO den schoeneren Code optimiert haette.



  • Der übliche Kompromiss, in dem drin steht, was gemeint ist (strlen) und nicht irgendwelche Funktionen bei jedem Schleifendurchlauf erneut aufgerufen werden:

    for(unsigned int i = 0, imax = strlen(szData); i < imax; ++i)
    

    Funktioniert hier genauso wie bei den leidigen end()-Abfragen, wenn man durch Container iteriert und den end()-Iterator nicht invalidiert 🙂


  • Mod

    fdfdg schrieb:

    this->that schrieb:

    Gute Compiler werden doch den Funktionsaufruf aus der Schleife rausziehen?

    Zumindest könnten sie es, bei Funktionen aus der Std-Lib ist ja klar, welche pure sind und welche nicht.

    Selbst der beste Compiler kann nicht wissen (ohne dass man es ihm auf irgendweine andere Weise mitteilt), dass die Sequenz kein 0xC3 enthält und folglich das Ergebnis von strlen nicht beeinflusst wird.



  • this->that schrieb:

    Weil man dann Gefaehr laeuft unnoetigerweise unleserlichen/frickeligen Code zu schreiben.

    Ich halte

    for (; *dataPtr != '\0'; ++dataPtr)
        *dataPtr ^= 0xC3;
    

    nicht für unleserlich. Mit etwas C- oder C++-Erfahrung versteht man sofort, was gemeint ist, und zwar um einiges besser als bei der Originalversion. Ich habe extra nicht

    while (*dataPtr)
        *dataPtr++ ^= 0xC3;
    

    geschrieben.

    Du kannst auch gerne

    for (unsigned int i = 0; data[i] != '\0'; ++i)
    

    verwenden, falls der Code so klarer ist. Finde ich besser als sich blind auf Optimierungen zu verlassen, zumal man dann tendiert, das auch bei komplexeren Situationen so handzuhaben, wo eine Optimierung nicht mehr möglich ist. Und selbst wenn der Compiler dein strlen() aus der Schleife ziehen könnte, würdest du die Anzahl Zeichen unnötigerweise doppelt zählen. Sehe ich in diesem Fall nicht als Premature Optimization an, weil die effiziente Lösung nicht wirklich schwieriger zu programmieren ist.

    Aber in solchen Situationen habe ich meist std::string , first/last -Iteratoren oder besonders bei binären Daten ein first/size -Paar, in allen Fällen stellt sich die Problematik nicht.

    this->that schrieb:

    Ist genauso wie mit den Leuten die Rueckgabeparameter per non-const Referenz uebergeben, weil sie meinen das sei viel Effizienter als mit by value return. Ergibt haesslicheren Code, obwohl jeder Compiler dank (N)RVO den schoeneren Code optimiert haette.

    In den Fällen, wo (N)RVO anwendbar ist, handelt es sich um lokale Objekte, wodurch eine Referenz als Rückgabetyp sowieso nie in Frage kommt.

    Aber ich weiss schon, worauf du hinauswillst 😉




Log in to reply