我有一个结构:
struct data{
int num1;
int num2;
int num3;
int num4;
}
现在,我可以转换单个元素,然后将它们放入缓冲区,但我想将整个结构复制到缓冲区(char buffer[sizeof(data)])。
有没有复制的方法
memcpy可以这样做
Microsoft系统可以使用memcpy_s自动检查大小
您还需要注意struct data
中的指针。
struct data {
int num1;
char* name;
}
char* name
所指向的内存的内容不会被memcpy复制。您将需要某种更复杂的序列化。
下面是一些有效的代码。它复制数据,然后显示结果
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;
}
在你对这个答案的评论中,
我正在尝试将这个结构体复制到闪存[内存芯片]。Flash读/写API传递一个字符串。
你揭示了你有一个XY问题——你问的是如何实现你的解决方案,而不是如何解决你的问题。你真的不想复制一个结构体到缓冲区,你想写数据在你的结构体到Flash使用一个API,需要一个char *
参数。
其他人指出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,您可能会有以下任何一个(假设您的内存是零初始化的,并且为了清晰起见是大端的):
<>之前/* 8位*/0x1234 5678 9ABC DEF0 1234 5678 9ABC DE00/* 16位*/0x1234 5678 009A BCDE F012 3456 789A BCDE/* 32位*/0x1234 5678 0000 000 000 000 000 009A BCDE F012 3456 789A 0000 000 000 000 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()
宏,但这会使使用结构体的计算变慢,并且在进行缓冲时可能会打包它。
首先,在结束大括号后面需要一个分号。其次,您应该使用类型定义。第三,应该大写用户类型(有些人建议在类型后面加上_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);
然而,我想问为什么你真的想要复制一个结构到一个字符缓冲区。你应该陈述你真正想要达到的目标,因为很有可能有更好的方法来实现它。
使用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 failedn");
return;
}
ob1.num1 = 1;
ob1.num2 = 2;
ob1.num3 = 3;
ob1.num4 = 4;
memcpy(buffer, &ob1, sizeof(struct data));
}
上面的答案只有在结构元素的大小都相同的情况下才有效(假设使用32位cpu和编译器)。所以int型是32位,但如果你的结构体中同时包含char型和int型,那么编译器可能会将char型延长到32位,以达到数据对齐的目的。
可以尝试对结构体的每个元素执行sprintf,并在将每个元素加载到字符缓冲区时将每个元素强制转换为正确的大小。
或者你可以一个元素一个元素地加载缓冲区,在每次写入缓冲区时,将索引的大小按正确的字节数递增。冗长但更有效的id资源是稀缺的,数据是巨大的。