简体   繁体   English

uint8_t到uint16_t的memcpy

[英]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.

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