我有一个这样的数组:
unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'};
unsigned char array2[6];
当我使用 memcpy 时:
memcpy(array2, array, 6);
然后打印它们:
printf("%x %x %x %x %x %x", array[0], // ... etc
printf("%x %x %x %x %x %x", array2[0], // ... etc
打印如下:
c0 3f e 54 e5 20
但另一个打印
ffffffc0 3f e 54 ffffffe5 20
发生了什么事?
最佳答案
我已经将您的代码变成了一个完整的可编译示例。我还添加了第三个“普通”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;
}
我的结果符合我的预期。
c0 3f e 54 e5 20
c0 3f e 54 e5 20
ffffffc0 3f e 54 ffffffe5 20
如您所见,只有当数组是有符号字符类型时,才会附加“额外”ff
。原因是当 memcpy
填充带符号的 char
数组时,设置了高位的值现在对应负 char
值。当传递给 printf
时,char
被提升为 int
类型,这实际上意味着符号扩展。
%x
以十六进制打印它们,就好像它们是 unsigned int
一样,但是由于参数是作为 int
传递的,因此行为在技术上是未定义的.通常在二进制补码机上,行为与使用 mod 2^N 算术的标准有符号到无符号转换相同(其中 N 是 unsigned int
中的值位数)。由于该值只是“轻微”负数(来自窄带符号类型),转换后该值接近最大可能的 unsigned int
值,即它有许多前导 1
的(二进制)或十六进制的前导 f
。
关于c++ - memcpy 将 ff ff ff 添加到一个字节的开头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3512749/