我有一个结构:
struct data{
int num1;
int num2;
int num3;
int num4;
}
现在,我可以转换单个元素,然后将它们放在缓冲区中,但我想将整个结构复制到缓冲区(char buffer [sizeof(data)])。
有没有办法复制?
答案 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(©_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缓冲区时将每个元素强制转换为正确的大小。
或者你可以通过使用递增索引的大小来加载缓冲区元素的大小,每次写入缓冲区时每个元素的正确字节数。冗长但可以说更有效的身份资源很少,数据也很大。