C++ típus konverzió

C++ típus konverzió
2021-10-22T10:45:23+02:00
2021-12-17T23:20:00+01:00
2022-10-15T21:20:48+02:00
BUH-X
Hello
Van egy memóriába beolvasott területem amire nem tudok fix struktúrát definiálni.
A tömböt char* -ként határozom meg. 
Van továbbá egy INT ami az aktuális olvasási pointer.

unsigned char *puffer; int pos;
Szeretnék kiolvasni a puffer[0]+pos+2 címről egy INT típusú  értéket. Csak több lépésben sikerül átkonvertálnom.

unsigned char *p2 = (unsigned char*)puffer; p2 += pos+2; int* pd2 = (int*)p2; int len = pd2[0];
Van erre szebb megoldás?

Köszönöm
Mutasd a teljes hozzászólást!
Használj rögzített méretű típusokat, pl `int32_t`:

int32_t val= *(int32_t *)(puffer+pos+2);
Ekkor már csak a big endian vs little endian okozhat gondot.
Mutasd a teljes hozzászólást!

  • Van erre szebb megoldás?

    Van, raadasul szerintem a te megoldasod nem is mukodik helyesen. Roviden igy lehet:

    static_cast<int>(*(puffer + pos + 2));
    Itt ossze tudod hasonlitani a kimeneteket: Compiler Explorer - C++ (x86-64 gcc 11.2)
    Nekem a te verziod 134678021 ad eredmenyul, az enyem 5-ot.

    A problema amugy szerintem ezzel a sorral van: int* pd2 = (int*)p2;
    Mutasd a teljes hozzászólást!
  • Nem teljesen jó. Meglehet nem jól definiáltam.



    unsigned char data[] =  { 1,0,0,0, 2,1,0,0, 3,0,0,0, 4,0,0,0, 5,0,0,0, 6, 7, 8 }; 



    int test_short(void) {
        unsigned char *puffer = data; 
        int pos = 2; 
        int x=static_cast<int>(*(puffer + pos + 2));
        return x;
    }
    258-at kellene visszakapnom. Az int az a 4 bájtból kell
    Mutasd a teljes hozzászólást!
  • Használj rögzített méretű típusokat, pl `int32_t`:

    int32_t val= *(int32_t *)(puffer+pos+2);
    Ekkor már csak a big endian vs little endian okozhat gondot.
    Mutasd a teljes hozzászólást!
  • C++-ban csak úgy nem lehet bájtokat máshogy értelmezni, mint ahogyan korábban reprezentálva voltak.
    Az első megoldásod és a javasolt megoldások 'undefined behaviour'-ök szerintem a  szabvány szerint.
    (jogosan, gondolj bele, hogy vannak olyan architektúrák, ahol pl egy int-nek fixen megfelelő align-olással kell rendelkeznie és elhasalnak a dolgok, amennyiben ez nem teljesül) 

    strict aliasing a kulcsszó!

    Valami ilyesmi a megoldás szerintem:

    template <class To> To safe_cast(const void* src) { To t; memcpy( &t, src, sizeof(t)); return t; } ... unsigned char data[] = { 1,0,0,0, 2,1,0,0, 3,0,0,0, 4,0,0,0, 5,0,0,0, 6, 7, 8 }; cout<<safe_cast<int>( data + 2)<<"\n";

    Persze itt még mindig csomó minden elcsúszhat, mint pl endianess..
    Alapból valami nem stimmel szerintem, amennyiben ilyen low-level szinten van szükséged parseolás-ra.
    Nem véletlenül vannak magas szintű könyvtárak adatok becsomagolására és feldolgozására akár egy telejsen más rendszeren. RAW bit reprezentációval csak szívni fogsz, nem célszerű így tárolni és továbbítani az adatokat..
    Mutasd a teljes hozzászólást!
  • Az adatokat nem én állítom össze.Bináris fájl.

    int val= *(int *)(puffer+pos+2); ^ | Ez a megoldás nem volt a tudástáramban.
    A többi is hasznos, igyekszem tanulni azokból is. 
    Köszönöm
    Mutasd a teljes hozzászólást!
  • Ez is igaz, láttam olyan architektúrát, ahol az illesztési követelmény miatt így kell:

    int32_t tmp; memcpy (&tmp, chaptr+offset, 4);
    Mutasd a teljes hozzászólást!
  • Tudom, hogy régi topic, de muszáj beleszóljak.
    Én soha nem csinálnék ilyen cast-olást! Ha szerencséd van a programod mindig elszáll, ha nem, akkor csak néha-néha aztán meg keresheted, hogy hol a hiba. A legnagyobb probléma az elcsúszás, vagy ahogy szoktuk mondani misalignment.

    A második probléma, hogy a tömbben hogy vannak a bájtok elrendezve, avagy endianness, ahogy már említették előttem is. Ha ezt nem tudod biztosan, akkor az egész csak egy tákolmány és próbálgatással fogod megoldani!

    Ha tegyük fel hálózatról kapod azt a streamet, akkor feltételezhetően big endian(aka network byte ordered) és akkor én valahogy így olvasnám ki:

    unsigned char data[] = { 1,0,0,0, 2,1,0,0, 3,0,0,0, 4,0,0,0, 5,0,0,0, 6, 7, 8 }; uint32_t val = 0; for (size_t i = 0; i < sizeof(val); ++i) { val <<= 8; val |= data[i]; }
    Mutasd a teljes hozzászólást!
  • Nem néztem végig a videót, de látom előszeretettel használja a pragma pack direktívát. Desktopon elmegy, de pl. egy embedded cuccban én nem használnám, ugyanis a kód jelentősen lassulhat miatta.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd