memcpy将ff ff ff添加到一个字节的开头

Hoc*_*ock 7 c++ memcpy

我有一个这样的数组:

unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'};
unsigned char array2[6];
Run Code Online (Sandbox Code Playgroud)

当我使用memcpy时:

memcpy(array2, array, 6);
Run Code Online (Sandbox Code Playgroud)

并打印它们:

printf("%x %x %x %x %x %x", array[0],  // ... etc
printf("%x %x %x %x %x %x", array2[0], // ... etc
Run Code Online (Sandbox Code Playgroud)

一个打印像:

c0 3f e 54 e5 20
Run Code Online (Sandbox Code Playgroud)

但另一个打印

ffffffc0 3f e 54 ffffffe5 20
Run Code Online (Sandbox Code Playgroud)

发生了什么?

CB *_*ley 13

我已将您的代码转换为完整的可编译示例.我还在char我的环境中添加了第三个"正常"数组.

#include <cstring>
#include <cstdio>

using std::memcpy;
using std::printf;

int main()
{

        unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'};
        unsigned char array2[6];
        char array3[6];

        memcpy(array2, array, 6);
        memcpy(array3, array, 6);

        printf("%x %x %x %x %x %x\n", array[0], array[1], array[2], array[3], array[4], array[5]);
        printf("%x %x %x %x %x %x\n", array2[0], array2[1], array2[2], array2[3], array2[4], array2[5]);
        printf("%x %x %x %x %x %x\n", array3[0], array3[1], array3[2], array3[3], array3[4], array3[5]);

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的结果是我的预期.

c0 3f e 54 e5 20
c0 3f e 54 e5 20
ffffffc0 3f e 54 ffffffe5 20
Run Code Online (Sandbox Code Playgroud)

如您所见,只有当数组是带符号的char类型时才会ff附加'extra' .原因是当memcpy填充signed数组时char,具有高位设置的值现在对应于负值char.当传递给printfchar被晋升为int类型这实际上意味着一个符号扩展.

%x以十六进制打印它们,就像它们一样unsigned int,但是因为int行为在技术上是未定义的,所以传递了参数.通常在二进制补码机器上,行为与使用mod 2 ^ N算术的无符号转换的标准相同(其中N是a中的值位数unsigned int).由于该值仅为"略微"负(来自窄签名类型),转换后该值接近最大可能unsigned int值,即它具有许多前导1(以二进制形式)或f以十六进制引导.


Has*_*kun 5

问题不是memcpy(除非您的 char 类型确实是 32 位,而不是 8 位),它在打印时看起来更像是整数符号扩展。

您可能想要更改您的 printf 以显式使用无符号字符转换,即。

printf("%hhx %hhx...", array2[0], array2[1],...);
Run Code Online (Sandbox Code Playgroud)

作为猜测,您的编译器/优化器可能正在处理array(其大小和内容在编译时已知)并且array2不同,首先将常量值推送到堆栈上,然后错误地推送符号扩展值。