uint8_t的memcpy到uint16_t

时间:2015-11-18 11:08:48

标签: c++

我有一个代码

#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;
}

(55-37的十六进制,11-B的十六进制) 其中我希望y包含“37B”(即, - 十进制 - 891)。但是,Y实际上包含“B37”(即十进制中的2871)。如何使用memcpy维护订单而不进行endian交换操作。

2 个答案:

答案 0 :(得分:3)

memcpy复制内存。它 维持内存字节的顺序。你无法让memcpy做其他事情。

你的问题是你不想复制记忆;你想做一些特殊的算术运算(例如,连接两个8位值来得到一个16位的值)。

确切地说,整数类型在内存中的布局方式是未指定的行为。在您的CPU上,memcpy hack不执行您想要的算术运算。因此,要做你想做的事,除了memcpy之外,还必须做一些事情。

我建议使用算术运算进行算术运算:你会得到代码,你可以肯定在所有 * 上工作,你的程序很可能与黑客行为相似(甚至更好)无论如何,特别是在打开编译器优化的情况下。

*:具有相关类型的所有内容,当然

答案 1 :(得分:1)

您获得B37的原因是因为您使用的是小端机器。

memcpy的调用正在做你期望的事情。值0x37将复制到y的第一个字节,而0x0B将复制到y的第二个字节。而且因为你是一个小端架构,y的第一个字节是最不重要的。因此它包含值0xB37

如果您希望x[0]为高字节且x[1]y的低字节,则需要以不依赖于字节序的方式执行此操作:

y = x[1];          // y = 0x0B
y |= x[0] << 8;    // y = 0x0B | 0x3700 = 0x370B

这会为y提供0x370B的值。但是,这仍然不是您期望的0x37B值。

如果这是你想要的,你需要认识到0x37B的高字节值为0x03而低字节的值为0x7B

因此,您需要按如下方式定义x

// note the use of hex constants to make the values more clear
uint8_t x[4] = {0x7b, 0x3, 0x0, 0x14};   

或者您需要执行一些额外的位移以获得所需的值:

y = x[1];          // y = 0x0B
y |= x[0] << 4;    // y = 0x0B | 0x370 = 0x37B