Aus gegebenen char array (char*) int32_t Werte performant extrahieren



  • Hallo zusammen,

    ich brauche mal wieder Hilfe bzw. einen Ratschlag. Ich habe ein char array (char*) mit gegebener Länge (daran kann ich leider nichts ändern).
    Nun muss ich daraus z.B. int32_t Werte auslesen, die sich an beliebigen Stellen befinden (Offset bekannt). Meine Frage ist nun, wie mache ich das am besten und am schnellsten?
    Zum Beispiel:
    Gegeben ist das Array mit der Länge 40. Nun weiß ich, dass an der Stelle 10 ein int32_t in LSB steht. Wie bekomme ich diesen nun am schnellsten extrahiert?

    Mein Ansatz bisher ist folgender:

    (_content[10]) | (_content[11] << 8) | (_content[12] << 16) | (_content[13] << 24)
    

    Ist dies der beste Weg um an den int32_t zu gelangen bzw. gibt es noch einen performanteren Weg ohne ganz unleserlich zu werden?

    Schöne Grüße und vielen Dank
    Quaneu

    Update:
    Es handelt sich doch nicht um unsigned char* sondern um char* =>

    ((unsigned char)_content[10]) | (((unsigned char)_content[11]) << 8) | (((unsigned char)_content[12]) << 16) | (((unsigned char)_content[13]) << 24)
    

  • Mod

    Wenn es auch systemabhängig sein darf: Direkt casten.



  • Wie wärs mit ner Funktion, die uintx_ts mithilfe der bereits erwähnten Methode extrahiert? Einfach casten würde nur auf Plattformen funktionieren, deren Endianess mit der der Daten übereinstimmt, zumal der Compiler da sicher wieder einfach nur ein casten draus macht, wenns passt.


  • Mod

    Techel schrieb:

    zumal der Compiler da sicher wieder einfach nur ein casten draus macht, wenns passt.

    Da habe ich Zweifel.



  • Ich traue dem Compiler einiges zu, ich testes einfach mal aus. Zur not macht man ein #if drum.



  • Vielen Dank für Antworten.

    Wenn es auch systemabhängig sein darf: Direkt casten.

    Ich hätte es gern systemunabhängig, da ich mich hier nicht einschränken will.



  • Ich teste bzw. spiele gerade mit meiner jetzigen Implementierung und habe in VS2015 ein ganz merkwürdiges verhalten...
    Wenn ich debugge bekomme ich 768 und wenn ich einen Breakpoint vor dem Code mache und den selben Code in der Überwachung laufen lasse 1001. Wie kann dass denn sein?

    Der Code:

    ((unsigned char)(_content[_position])) | (((unsigned char)(_content[++_position])) << 8) | (((unsigned char)(_content[++_position])) << 16) | (((unsigned char)(_content[++_position])) << 24)
    

    bzw.

    ((unsigned char)(_content[_position++])) | (((unsigned char)(_content[_position++])) << 8) | (((unsigned char)(_content[_position++])) << 16) | (((unsigned char)(_content[_position++])) << 24)
    

    Ich habe im Array _content (char*) folgende Werte: -23 3 0 0 (1001) Und _position ist 0



  • Die Reihenfolge der Auführung gleichwertiger Operatoren ist meist undefiniert: http://en.cppreference.com/w/cpp/language/eval_order



  • Dein Code ist UB. Du erhöhst innerhalb des Ausdrucks mehrfach "position".
    Nimm position, position+1, ...



  • Ok. Vielen Danke. Da ich von C# komme und es da keine Probleme bzw. UB ist war ich erstmal irritiert.



  • Um Performance musst du dir keine große Gedanken machen.
    Wie du hier sehen kannst, erzeugt der Compiler aus dem ganzen Geshifte optimalen Code:
    https://godbolt.org/g/Uf13ly



  • Hm naja, als Nachtrag sei zu erwähnen, dass offenbar nur GCC dazu in der Lage ist. Alle anderen Compiler (clang, icc, vc++) scheitern kläglich an dieser simplen Aufgabe, aber es zwingt dich ja niemand dazu, diese einzusetzen.


Anmelden zum Antworten