comportamento estranho de memcpy

Oct 26 2020

Quero copiar um inteiro longo sem sinal para o buffer char, byte por byte. Se eu usar a linha em comentário, ela não será copiada para o buffer.

    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]);
    }

A seguir está a saída de duas execuções com cada valor:

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)

Respostas

4 EricPostpischil Oct 26 2020 at 17:42

Em hexadecimal, 268435456 é 10000000 16 . Seu C ++ armazena os bytes de um unsigned longna memória com o byte de baixo valor anterior na memória, então isso é armazenado na memória como bytes com os valores 00 16 , 00 16 , 00 16 , 10 16 .

memcpycopia corretamente esses bytes em buf.

Então, ao strlen(buf)examinar buf, ele encontra um byte nulo (00 16 ) primeiro. Isso indica que a string de caracteres em buftem comprimento zero, pois o caractere de terminação aparece imediatamente no início. Portanto, strlen(buf)retorna zero.

Uma vez que esse valor de retorno é atribuído a len, o loop for (int i = 0; i < len; i++)executa zero iterações.

Da mesma forma, em cout << "Value after unsigned long int copy - buf: " << buf << endl;, bufcontém uma string de comprimento zero, portanto, nenhum caractere é impresso para ela.

5 eerorika Oct 26 2020 at 17:31

não é copiado para o buffer.

Sim, ele é.

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

Não está claro por que você não esperava a saída que vê. 0 é o valor do caractere terminador nulo. Se o byte de ordem de memória mais baixo do inteiro for 0, o buffer conterá a string terminada em nulo que representa a string vazia. Nesse caso, a saída que você vê é esperada. Em sistemas little endian (e também em sistemas big endian onde longé maior que 4 bytes) esse é o caso de 268435456 que é 0x10'00'00'00 em hexadecimal.

Só porque os bytes que você copiou representam a string vazia, não significa que os bytes não foram copiados.