C语言 将结构复制到缓冲区

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5589136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:19:35  来源:igfitidea点击:

Copy struct to buffer

c

提问by Punit

I have a structure:

我有一个结构:

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

Now, I can convert individual elements and then put them in a buffer, but I want to copy the whole structure into a buffer(char buffer[sizeof(data)]).

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

Is there a way to copy ?

有没有办法复制?

回答by Eric

memcpycan do this

memcpy可以做到这一点

Microsoft systems can use memcpy_sfor an automated check on sizes

Microsoft 系统可以使用memcpy_s自动检查大小

You also need to be aware of pointers inside struct data.

你还需要注意里面的指针struct data

struct data { 
    int num1;
    char* name;
}

the content of the memory pointed by char* namewill not be copied by memcpy. You will need some kind of serialization which is a little more complicated.

char* namememcpy 不会复制指向的内存内容。您将需要某种更复杂的序列化。

Here is some valid code that does it. It copies the data to and from then displays the result

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

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

回答by Kevin Vermeer

In your comment to this answer,

在您对此答案的评论中,

I am trying to copy this struct to a flash [memory chip]. And the Flash read/write API passes a string. – Punit 2 hours ago

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

you reveal that you've got an XY Problem- You're asking how to implement your idea of a solution, not how to solve your problem. You don't really want to copy a struct to a buffer, you want to write data in your struct to Flash using an API that requires a char *argument.

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

Others have pointed out that memcpywill do what you want. But they all involve allocating memory for this buffer in RAM. Using these approaches will work, but they'll waste time and memory. Assuming that your Flash API has a function to the effect of:

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

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

and you've stored your structure in a variable called data_var, you can use your API in an identical fashion to memcpy:

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

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

To be clearer and avoid the cast, you may wish to wrap this in a union:

为了更清楚并避免强制转换,您可能希望将其包装在联合中:

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

This will allow you to call it with a more traditional syntax.

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

Note that both methods (and memcpy!) could fail if you've got a non-contiguous structure. For instance, perhaps your structure looks like this:

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

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

If you're on anything other than an 8-bit system, such a structure is likely (depending on your architecture) to contain gaps. For example, assuming num1 is 0x12345678, num2 is 0x9A, num3 is 0xBCDEF0123456789A, and num4 is 0xBCDE, you might have any the following (assuming that your memory is zero-initialized, and big-endian for clarity):

如果您使用的不是 8 位系统,那么这样的结构很可能(取决于您的架构)包含间隙。例如,假设 num1 是 0x12345678,num2 是 0x9A,num3 是 0xBCDEF0123456789A,而 num4 是 0xBCDE,你可能有以下任何情况(假设你的内存是零初始化的,为了清楚起见,大端):

    /* 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

In this case, you'll have to use something more ugly, like the following function:

在这种情况下,您将不得不使用更难看的东西,例如以下函数:

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

or the #pragma pack()macro, but that could make computations using the struct slower, and you'd probably rather pack it when you're going to do the buffering.

#pragma pack()宏,但这可能会使使用结构的计算速度变慢,并且您可能宁愿在要进行缓冲时将其打包。

回答by Jim Balter

First, you need a semicolon after the closing brace. Second you should use typedefs. Third, you should capitalize user types (some people recommend putting _t after your types, but that actually violates the C standard because such names are reserved). Fourth, you need a value of that type to copy. Considering all that:

首先,右大括号后需要一个分号。其次,您应该使用 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);

However, I would question why you actually want to copy a structure to a char buffer. You should state what you're actually trying to achieve, because there's a good chance that there's a better way to go about it.

但是,我会质疑为什么您实际上要将结构复制到字符缓冲区。你应该说明你真正想要达到的目标,因为很有可能有更好的方法来实现它。

回答by Nallu

Using memcpy will enable the entire structure to be copied into a buffer. For eg., contents of 'ob1' are copied into 'buffer' in the following code:

使用 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));

    }

回答by user2578174

The answer above will only work if the size of the struct elements are all of the same size (assuming using a 32 bit cpu and compiler). So ints will be 32 bits each but if your struct contains a char for example as well as ints then the compiler is likely to pad out the char to 32 bits for data alignment purposes.

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

You could try sprintf on each of the elements of the struct and casting each element to the correct size as you load each element into the char buffer.

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

Or you could just load the buffer element by element using an incrementing the index by the size the correct number of bytes for each element on each write to the buffer. Long winded but arguably more efficient id resources are scarce and data is big.

或者,您可以使用每次写入缓冲区时每个元素的正确字节数的大小递增索引,逐个元素地加载缓冲区。冗长但可以说更有效的 id 资源稀缺,数据量大。