简体   繁体   English

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

[英]memcpy adds ff ff ff to the beginning of a byte

I have an array that is like this: 我有一个这样的数组:

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

When I use memcpy: 当我使用memcpy时:

memcpy(array2, array, 6);

And print both of them: 并打印它们:

printf("%x %x %x %x %x %x", array[0],  // ... etc
printf("%x %x %x %x %x %x", array2[0], // ... etc

one prints like: 一个打印像:

c0 3f e 54 e5 20

but the other one prints 但另一个打印

ffffffc0 3f e 54 ffffffe5 20

what happened? 发生了什么?

I've turned your code into a complete compilable example. 我已将您的代码转换为完整的可编译示例。 I also added a third array of a 'normal' char which on my environment is signed. 我还在我的环境中添加了第三个“普通” 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;
}

My results were what I expected. 我的结果是我的预期。

c0 3f e 54 e5 20
c0 3f e 54 e5 20
ffffffc0 3f e 54 ffffffe5 20

As you can see, only when the array is of a signed char type do the 'extra' ff get appended. 如您所见,只有当数组是带符号的char类型时,才会附加' ff The reason is that when memcpy populates the array of signed char , the values with a high bit set now correspond to negative char values. 原因是当memcpy填充signed char数组时,高位设置的值现在对应于负char值。 When passed to printf the char are promoted to int types which effectively means a sign extension. 传递给printfchar被提升为int类型,这实际上意味着符号扩展。

%x prints them in hexadecimal as though they were unsigned int , but as the argument was passed as int the behaviour is technically undefined. %x以十六进制打印它们,就好像它们是unsigned int ,但是当参数作为int传递时,行为在技术上是未定义的。 Typically on a two's complement machine the behaviour is the same as the standard signed to unsigned conversion which uses mod 2^N arithmetic (where N is the number of value bits in an unsigned int ). 通常在二进制补码机器上,行为与使用mod 2 ^ N算法的无符号转换的标准相同(其中N是unsigned int的值位数)。 As the value was only 'slightly' negative (coming from a narrow signed type), post conversion the value is close to the maximum possible unsigned int value, ie it has many leading 1 's (in binary) or leading f in hex. 由于该值仅为“略微”负(来自窄签名类型),因此转换后该值接近最大可能的unsigned int整数值,即它具有许多前导1 (以二进制形式)或前导f以十六进制表示。

The problem is not memcpy (unless your char type really is 32 bits, rather than 8), it looks more like integer sign extension while printing. 问题不是memcpy (除非你的char类型确实是32位,而不是8位),它看起来更像是打印时的整数符号扩展。

you may want to change your printf to explicitly use unsigned char conversion, ie. 您可能希望更改printf以显式使用unsigned char转换,即。

printf("%hhx %hhx...", array2[0], array2[1],...);

As a guess, it's possible that your compiler/optimizer is handling array (whose size and contents are known at compile time) and array2 differently, pushing constant values onto the stack in the first place and erroneously pushing sign extended values in the second. 猜测,你的编译器/优化器可能正在处理array (其大小和内容在编译时已知)和array2不同,首先将常量值推入堆栈并在第二个位置错误地推送符号扩展值。

您应该屏蔽高位,因为在调用varargs函数时,字符将扩展为int大小:

printf("%x %x %x %x %x %x", array[0] & 0xff,  // ..

%x format expects integer type. %x格式需要整数类型。 Try to use casting: 尝试使用铸造:

printf("%x %x %x %x %x %x", (int)array2[0], ...

Edit: Since there are new comments on my post, I want to add some information. 编辑:由于我的帖子有新的评论,我想添加一些信息。 Before calling the printf function, compiler generates code which pushes on the stack variable list of parameters (...). 在调用printf函数之前,编译器会生成代码,这些代码会推送参数的堆栈变量列表(...)。 Compiler doesn't know anything about printf format codes, and pushes parameters according to their type. 编译器对printf格式代码一无所知,并根据类型推送参数。 printf collects parameters from the stack according to formatting string. printf根据格式化字符串从堆栈中收集参数。 So, array[i] is pushed as char, and handled by printf as int. 因此,array [i]被推送为char,并由printf作为int处理。 Therefore, it is always good idea to make casting, if parameter type doesn't match exactly format specification, working with printf/scanf functions. 因此,如果参数类型与格式规范不完全匹配,则使用printf / scanf函数进行强制转换始终是个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM