【问题标题】:C memcpy to struct allocationC memcpy 到结构分配
【发布时间】:2019-10-30 20:41:55
【问题描述】:

我编写了一个简单的程序来测试使用 memcpy 将字节从字节缓冲区复制到结构中。但是我没有得到预期的结果。

我分配了一个 100 字节的缓冲区,并将值设置为 0、1、2...99。 然后我将字节复制到一个 16 字节的结构中。

某处字节 0x01 丢失。我正在尝试了解正在发生的事情

#include <stdio.h>
#include <stdint.h>

struct Test {

    uint8_t a;
    uint16_t b;
    uint32_t c;
    uint64_t d;
    uint8_t e;
};

int main(int argc, char** argv) {

    uint8_t buffer[100];
    for (uint8_t i = 0; i < 100; i++) {
        buffer[i] = i;
    }

    struct Test test;
    memcpy(&test, buffer, sizeof(struct Test));

    printf("A is %ld and should be %ld\n", test.a, 0x00);
    printf("B is %ld and should be %ld\n", test.b, 0x0201);
    printf("C is %ld and should be %ld\n", test.c, 0x06050403);
    printf("D is %ld and should be %ld\n", test.d, 0x1413121110090807);
    printf("E is %ld and should be %ld\n", test.e, 0x15);
}

我得到以下结果:

A is 0 and should be 0
B is 770 and should be 513
C is 117835012 and should be 100992003
D is 1084818905618843912 and should be 1446519769808832519
E is 16 and should be 21

770(B 值)是字节 0302,而不是 0201(int 513)

【问题讨论】:

  • 你需要阅读结构中的padding
  • 是的,如果输出十六进制%lx会更容易看到效果。

标签: c memcpy


【解决方案1】:

原因是编译器已将 padding 添加到您的结构中,以确保 b 在 16 位边界上对齐。因此,第二个字节未被使用。

如果您开始重新排序结构,您会看到更大的变化。同样,32 位和 64 位值将需要适合其类型的对齐方式。因此,由于填充,您最终可能会出现明显的“漏洞”。试试看!

您通常会看到具有reserved 成员的结构(尤其是二进制格式),而不是依赖于填充。

【讨论】:

  • 嗯,有道理。菜鸟失误。所以我猜测consesus是不要使用memcpy来做这种类型的操作。最好手动分配每个变量 (a = buffer[0], b = buffer[2]
  • 这完全取决于您要达到的目标。使用memcpy 从/向缓冲区读取和写入结构是很常见的。但是在对执行环境进行外部假设时必须小心(例如在代码中硬编码内存内容,或从文件中读取)
  • @user2840470 不一定。 字节流 memcopied 到结构中的一个常见实际用途是当您接收网络数据并且第 N 级协议的有效负载必须转发到第 (N+1) 级协议(例如,IP数据包有效负载被转发到 TCP)。在这种情况下,这只是一个设计问题:struct 被设计为 packed-data 友好,并且 PACK/UNPACK 宏始终存在于移植层中以管理特殊情况。所以问题是:可以更改您的结构以使 packed-data 友好吗? :)(顺便说一句:问答+1。有趣的话题)
  • @Cubo78 现在我看到结构以某些方式布局的原因是有道理的。我绝对可以更改结构的顺序以更好地匹配单词边界。感谢您解释更多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2016-02-12
相关资源
最近更新 更多