【问题标题】:Copy struct into char array将结构复制到 char 数组中
【发布时间】:2014-12-13 08:34:42
【问题描述】:

我正在学习 C 并且对结构有疑问。

我有一个

struct myStruct {
    char member1[16];
    char member2[10];
    char member3[4];
};

这至少需要 30 字节的内存来存储。是否可以将所有这些数据复制到变量char foo[30] 中?语法是什么?

【问题讨论】:

  • 不是肯定的,但你可以试试 memcpy(*dest, *src, sizeof(src));
  • 如果您发现自己说了“显然”之类的话,您应该立即提出多个危险信号。
  • @KerrekSB 不是需要 30 个字节吗?我知道对于更复杂的话题我应该更加谨慎
  • @YiweiG:问题是,你不能确定地知道。因此,除非您实际上可以备份,否则任何事情都不应该是“显而易见的”。橡皮鸭,手头有标准参考,然后我们可以谈论“明显”。
  • @KerrekSB 很公平。我已经编辑了帖子以进行澄清

标签: c struct


【解决方案1】:

您不能直接复制整个内容,因为编译器可能会任意决定如何填充/打包此结构。你需要三个memcpy 调用:

struct myStruct s;
// initialize s
memcpy(foo,                                       s.member1, sizeof s.member1);
memcpy(foo + sizeof s.member1,                    s.member2, sizeof s.member2);
memcpy(foo + sizeof s.member1 + sizeof s.member2, s.member3, sizeof s.member3);

【讨论】:

  • 如果char 数组的语义是原始字节,这是正确的。如果它们是 NUL 终止字符串,则需要另一种解决方案(例如 Triton Man's answer)。从问题中不清楚它是什么。
  • 这种技术是否被称为serializing? (它会避免填充问题吗?)
  • 与其手动计算结构中每个字段的偏移量,不如使用宏来完成。
  • 我可以用&foo[16]代替foo + sizeof s.member1吗?
  • 是的,没关系。为了便于维护,我只是使用了sizeof
【解决方案2】:

struct myStruct 的大小是 sizeof(struct myStruct),仅此而已。它至少是 30,但它可以是更大的值。

你可以这样做:

char foo[sizeof(struct myStruct)];

struct myStruct x; /* populate */

memcpy(foo, &x, sizeof x);

【讨论】:

  • 问题是 printf("%s", foo) 只会显示第一个 char 数组,假设它们是空终止的字符串。
  • 你可以使用 offsetof() 来获取不在第一个位置的字符串。
  • 如果结构的成员不是 char 但假设是一堆整数或整数和字符的混合,这仍然有效吗?
【解决方案3】:

根据 C 标准(6.2.6 类型的表示)

4 存储在任何其他对象类型的非位域对象中的值 由 n × CHAR_BIT 位组成,其中 n 是该对象的大小 类型,以字节为单位。该值可以复制到类型的对象中 unsigned char [n](例如,by memcpy);结果的字节集是 称为值的对象表示。

所以你可以简单地写

unsigned char foo[sizeof( struct myStruct )];
struct myStruct s = { /*...*/ };

memcpy( foo, &s, sizeof( struct myStruct ) );

考虑到您可以将数据成员分别复制到一个数组中。例如

unsigned char foo[30];
struct myStruct s = { /*...*/ };

unsigned char *p = foo;
memcpy( p, s.member1, sizeof( s.member1 ) );
memcpy( p += sizeof( s.member1 ), s.member2, sizeof( s.member2 ) );
memcpy( p += sizeof( s.member2 ), s.member3, sizeof( s.member3 ) );

【讨论】:

  • 虽然这是有效的 C,但不一定能满足 OP 的要求。
  • @5gon12eder 我没听懂你想说什么。无论如何,我是决定他想要什么的 OP。
  • 我的猜测是他实际上想要foo = s.member1 + s.mamber2 + s.member3,因为我们会用 Python 编写它,+ 执行列表连接。正如您在答案中很好解释的那样,您的解决方案将复制对象的字节。
【解决方案4】:

是的,有可能。

您可以通过不同的方式来执行此操作。以下是两种最简单的方法。

struct myStruct  myVar;

/* Initialize myVar */
...

memcpy (foo, &myVar, sizeof (myStruct));

或者如果你正在处理一个指针......

struct myStruct *  myVarPtr;

/* Initialize myVarPtr */
...

memcpy (foo, myVarPtr, sizeof (myStruct));

请注意,当像这样将结构复制到/从字符数组中时,您必须非常小心,因为结构大小并不总是您首先想到的。在您的特定情况下,可能没有任何问题;但总的来说,您至少应该注意可能会改变结构大小的潜在填充、对齐和类型大小问题。

希望这会有所帮助。

【讨论】:

    【解决方案5】:

    如果您有一个名为 st 的 myStruct 变量,您可以执行以下操作:

    strcpy(foo, st.member1);
    strcat(foo, st.member2);
    strcat(foo, st.member3);
    

    【讨论】:

    • 如果数组不是以 null 结尾或者比描述的短,则不会工作。
    • 是的,假设它们是字符串。
    • 加上永远不要使用 strcpy。 :P 始终使用 strncpy。
    • 消除歧义(仅针对此答案)规范。你假设空终止的字符串。 (我知道OP没有指定)
    【解决方案6】:

    使用 memcpy 非常简单。

    char foo[30];
    struct myStruct s;
    
    s.member1 = //some data
    s.member2 = //some data
    s.member3 = //some data
    
    memcpy(foo, &s, 30);
    

    【讨论】:

      猜你喜欢
      • 2020-01-04
      • 1970-01-01
      • 2013-05-15
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      相关资源
      最近更新 更多