[英]memcpy of uint8_t to uint16_t
I have a code 我有一个密码
#include <iostream>
#include <string.h>
using namespace std;
int main() {
// your code goes here
uint8_t x[4] = {55, 11, 0, 20};
uint16_t y;
memcpy(&y, &x[0], 2);
std::cout<<y<<std::endl;
return 0;
}
(hex of 55 - 37, hex of 11 - B) in which I expect y to contain "37B"(ie, - 891 in decimal). (我希望y包含“ 37B”(即-十进制为891)(55-37的十六进制,11-B的十六进制)。 But, Y actually contains "B37"(ie, 2871 in decimal). 但是,Y实际上包含“ B37”(即,十进制的2871)。 How to maintain the order with memcpy without endian swap operation. 如何使用memcpy维护订单而不进行字节序交换操作。
memcpy
copies memory. memcpy
复制内存。 And it does maintain the order of the bytes of memory. 而且它确实保持了内存字节的顺序。 You can't make memcpy
do something else. 您不能让memcpy
做其他事情。
Your problem is that you don't want to copy memory; 您的问题是您不想复制内存。 you want to do some particular arithmetic operation (eg concatenate two 8-bit values to get a 16-bit value). 您想执行一些特殊的算术运算(例如,将两个8位值连接起来以获得16位值)。
Exactly how integer types are laid out in memory is unspecified behavior. 整数类型在内存中的确切布局方式是未指定的行为。 On your CPU, your memcpy
hack does not perform the arithmetic operation you want. 在您的CPU上,您的memcpy
hack无法执行您想要的算术运算。 Thus, to do what you want, have to do something other than (or in addition to) memcpy
. 因此,要做您想做的事情,除了memcpy
之外(或除了memcpy
),还必须做其他的事情。
I advise doing the arithmetic operation with arithmetic operations: you'll get code you can be sure works on everything * , and your program will most likely perform similarly (or even better) than the hack anyways, especially with compiler optimizations turned on. 我建议使用算术运算来进行算术运算:您将获得可以确保在所有*上都能正常工作的代码,并且无论如何,您的程序很有可能会表现出与hack类似(甚至更好)的性能,尤其是在启用编译器优化的情况下。
*: everything that has the relevant types, of course *:当然,所有具有相关类型的东西
The reason you're getting B37
is because you're on a little-endian machine. 获得B37
的原因是因为您使用的是B37
字节序的计算机。
The call to memcpy
is doing what you would expect. 给memcpy
的电话正在做您期望的事情。 The value 0x37
is copied to the first byte of y
, while 0x0B
is copied to the second byte of y
. 值0x37
复制到y
的第一个字节,而0x0B
复制到y
的第二个字节。 And because you're on a little-endian architecture, the first byte of y
is the least significant. 而且由于您使用的是低端字节序架构,因此y
的第一个字节是最低有效的。 So it contains the value 0xB37
. 因此它包含值0xB37
。
If you want x[0]
to be the high byte and x[1]
to be the low byte of y
, you need to do it in a way that doesn't depend on endianness: 如果希望x[0]
是x[1]
的高字节, x[1]
是y
的低字节,则需要以不依赖于字节序的方式进行操作:
y = x[1]; // y = 0x0B
y |= x[0] << 8; // y = 0x0B | 0x3700 = 0x370B
This will give y
a value of 0x370B
. 这将使y
的值为0x370B
。 However this is still not the 0x37B
value you expect. 但是,这仍然不是您期望的0x37B
值。
If that's what you want, you need to recognize that 0x37B
has a value of 0x03
for the high byte and 0x7B
for the low byte. 如果这是您想要的,则需要认识到0x37B
的高字节为0x03
,低字节为0x7B
。
So you would either need to define x
as follows: 因此,您要么需要定义x
,如下所示:
// note the use of hex constants to make the values more clear
uint8_t x[4] = {0x7b, 0x3, 0x0, 0x14};
Or you would need to perform some additional bit shifting to get the values you need: 否则,您将需要执行一些其他的移位操作以获得所需的值:
y = x[1]; // y = 0x0B
y |= x[0] << 4; // y = 0x0B | 0x370 = 0x37B
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.