将struct复制到缓冲区

时间:2011-04-08 00:28:23

标签: c

我有一个结构:

struct data{
 int num1;
 int num2;
 int num3;
 int num4;
}

现在,我可以转换单个元素,然后将它们放在缓冲区中,但我想将整个结构复制到缓冲区(char buffer [sizeof(data)])。

有没有办法复制?

5 个答案:

答案 0 :(得分:7)

memcpy可以做到这一点

Microsoft系统可以使用memcpy_s自动检查尺寸

您还需要了解struct data内的指针。

struct data { 
    int num1;
    char* name;
}

memcpy不会复制char* name指向的内存内容。你需要某种更复杂的序列化。

这是一些有效的代码。它会复制数据,然后显示结果

struct data{
  int num1;
  int num2;
  int num3;
};

int main(int argc, char** argv)
{
   data my_data;
   my_data.num1 = 64;
   my_data.num2 = 65;
   my_data.num3 = 66;

   char buffer[20];
   memcpy(buffer, &my_data, sizeof(data));

   data copy_data;
   memcpy(&copy_data, buffer, sizeof(data));

   printf("the numbers : %d - %d - %d \n", copy_data.num1, copy_data.num2, copy_data.mum3);



   return 0;
}

答案 1 :(得分:6)

在您对this answer的评论

  

我正在尝试将此结构复制到闪存[内存芯片]。 Flash读/写API传递一个字符串。 - Punit 2小时前

你透露你有XY Problem - 你问的是如何实现你的解决方案的想法,而不是如何解决你的问题。您真的不想将结构复制到缓冲区,您希望使用需要char *参数的API将结构中的数据写入Flash。

其他人指出memcpy会做你想做的事。但它们都涉及在RAM中为此缓冲区分配内存。使用这些方法会起作用,但它们会浪费时间和记忆。假设您的Flash API具有以下功能:

int WriteBlock(int address, char *data, int length);

并且您已将结构存储在名为data_var的变量中,您可以使用与memcpy相同的API:

int success = WriteBlock(my_address, (char *) &data_var, sizeof(struct data)

为了更清楚并避免演员表演,你可能希望将它包装在一个联盟中:

union {
    struct data{
        int num1;
        int num2;
        int num3;
        int num4;
    };
    char data_arr[sizeof(struct data)];
};

这将允许您使用更传统的语法来调用它。

请注意,如果您有一个非连续的结构,两个方法(和memcpy!)都可能失败。例如,您的结构可能如下所示:

struct data{
 int   num1;
 char  num2;
 long  num3;
 short num4;
}

如果你使用的不是8位系统,那么这种结构很可能(取决于你的架构)来控制间隙。 例如,假设num1为0x12345678,num2为0x9A,num3为0xBCDEF0123456789A,num4为0xBCDE,则可能具有以下任意内容(假设您的内存为零初始化,为了清晰起见为big-endian):

    /* 8-bit */
    0x1234 5678 9ABC DEF0 1234 5678 9ABC DE00
    /* 16-bit */
    0x1234 5678 009A BCDE F012 3456 789A BCDE
    /* 32-bit */
    0x1234 5678 0000 0000 0000 009A BCDE F012 3456 789A 0000 0000 0000 BCDE

在这种情况下,你将不得不使用更丑陋的东西,如下面的函数:

int fillDataBuffer(struct data d, char *buffer, int len) 
{
  int i, j = 0;

  for (i = sizeof(d.num1) - 1; i >= 0 && j < len; i--, j++) {
    buffer[j] = (char) (d.num1 >> i); 
  }
  for (i = sizeof(d.num2) - 1; i >= 0 && j < len; i--, j++) {
    buffer[j] = (char) (d.num2 >> i); 
  }
  for (i = sizeof(d.num3) - 1; i >= 0 && j < len; i--, j++) {
    buffer[j] = (char) (d.num3 >> i); 
  }
  for (i = sizeof(d.num4) - 1; i >= 0 && j < len; i--, j++) {
    buffer[j] = (char) (d.num4 >> i); 
  }

  if (j >= len) {
    /* Error!  The buffer wasn't big enough. */
    return 0;
  } else {
    return 1;
  }
}

#pragma pack()宏,但这可能会使使用结构的计算速度变慢,而且当你要进行缓冲时,你可能宁愿打包它。

答案 2 :(得分:1)

首先,在结束括号后需要一个分号。其次你应该使用typedef。第三,你应该大写用户类型(有些人建议在你的类型之后放置_t,但这实际上违反了C标准,因为这些名称是保留的)。第四,您需要复制该类型的值。考虑到所有这些:

typedef struct{
 int num1;
 int num2;
 int num3;
 int num4;
} Data;

Data foo = { 1, 2, 3, 4};
char buffer[sizeof foo]; // at least

memcpy(buffer, &foo, sizeof foo);

但是,我会问你为什么要将结构复制到char缓冲区。你应该陈述你实际想要实现的目标,因为很有可能有更好的方法来实现它。

答案 3 :(得分:1)

使用memcpy可以将整个结构复制到缓冲区中。 例如,'ob1'的内容被复制到'buffer'中,代码如下:

 #include <stdio.h>
 #include <stdlib.h>      
 #include <string.h>

    struct data{
        int num1;
        int num2;
        int num3;
        int num4;
    };
    int main()
    {
        struct data ob1;
        struct data *buffer = (struct data *)malloc(sizeof(struct data));
        if(buffer == NULL)
            {
               printf("Memory allocation failed\n");
               return;
            }

        ob1.num1 = 1;
        ob1.num2 = 2;
        ob1.num3 = 3;
        ob1.num4 = 4;

        memcpy(buffer, &ob1, sizeof(struct data));

    }

答案 4 :(得分:0)

只有struct元素的大小都相同(假设使用32位cpu和编译器),上面的答案才有效。因此,每个int将是32位,但如果你的struct包含一个char,例如int,那么编译器可能会将char填充为32位以进行数据对齐。

您可以在结构的每个元素上尝试sprintf,并在将每个元素加载到char缓冲区时将每个元素强制转换为正确的大小。

或者你可以通过使用递增索引的大小来加载缓冲区元素的大小,每次写入缓冲区时每个元素的正确字节数。冗长但可以说更有效的身份资源很少,数据也很大。