dziwne zachowanie memcpy

Oct 26 2020

Chcę skopiować nieoznaczoną długą liczbę całkowitą do bufora char bajt po bajcie. Jeśli używam linii pod komentarzem, nie jest ona kopiowana do bufora.

    char buf[128];
    //unsigned long int_val = 268435456;
    unsigned long int_val = 293456376;

    cout << "Value of int_val: " << int_val << endl;

    memset(buf, 0, sizeof(buf));

    memcpy(buf, &int_val, sizeof(long));
    cout << "Value after unsigned long int copy - buf: " << buf << endl;

    const int len = strlen(buf);
    cout << "buf" << endl << "====" << endl;
    for (int i = 0; i < len; i++)
    {
        printf("%3d (0x%02X)\n", buf[i], buf[i]);
    }

Poniżej przedstawiono wyniki dwóch przebiegów z każdą wartością:

Value of int_val: 268435456
Value after unsigned long int copy - buf:
buf
===

Value of int_val: 293456376
Value after unsigned long int copy - buf: ��}
buf
===
 -8 (0xFFFFFFF8)
-55 (0xFFFFFFC9)
125 (0x7D)
 17 (0x11)

Odpowiedzi

4 EricPostpischil Oct 26 2020 at 17:42

Szesnastkowo 268435456 to 10000000 16 . Twój C ++ przechowuje bajty unsigned longw pamięci z bajtem o niskiej wartości wcześniej w pamięci, więc jest on przechowywany w pamięci jako bajty o wartościach 00 16 , 00 16 , 00 16 , 10 16 .

memcpypoprawnie kopiuje te bajty do buf.

Następnie podczas strlen(buf)badania najpierw bufznajduje bajt zerowy (00 16 ). Oznacza to, że ciąg znaków w bufma zerową długość, ponieważ znak kończący pojawia się natychmiast na początku. Więc strlen(buf)zwraca zero.

Ponieważ ta wartość zwracana jest przypisana do len, pętla for (int i = 0; i < len; i++)wykonuje zerowe iteracje.

Podobnie, w cout << "Value after unsigned long int copy - buf: " << buf << endl;, bufzawiera ciąg zerowej długości, więc żadne znaki są drukowane na nim.

5 eerorika Oct 26 2020 at 17:31

nie jest kopiowany do bufora.

Tak to jest.

cout << ... << buf << endl;
const int len = strlen(buf);

Nie jest jasne, dlaczego nie spodziewałeś się rezultatu, który widzisz. 0 jest wartością znaku kończącego wartość null. Jeśli najniższy bajt kolejności pamięci liczby całkowitej wynosi 0, wówczas bufor zawiera ciąg zakończony znakiem null, który reprezentuje pusty ciąg. W takim przypadku oczekiwany jest wynik, który widzisz. W systemach typu little endian (a także w systemach big endian, w których longjest szersza niż 4 bajty), tak się dzieje w przypadku 268435456, czyli 0x10'00'00'00 szesnastkowo.

Tylko dlatego, że skopiowane bajty reprezentują pusty ciąg, nie oznacza, że ​​bajty nie zostały skopiowane.