考虑以下结构:
typedef struct __attribute__((packed)) a{
int a1;
int b2;
char cArray[5];
int c3;
} Mystruct;
现在在我的代码中,我这样做:
char source[50];
Mystruct mm;
//...
//initialization and other codes
//...
memcpy(&mm,source,sizeof(mm));
我试图从字符串填充结构(从文件中更具体),因此我不想填充。但是认为包装也会影响性能。
所以我的问题是,还有其他方法可以实现我的目标吗? 是否可以使用c ++中的类的成员变量执行相同的操作(从字符串填充)?如果是,怎么样?
答案 0 :(得分:5)
我强烈建议您购买并阅读Write Portable Code。你不想采取这种方法。不仅因为它不可移植(想想endianess问题),而且确实会影响性能和原子性(非对齐的32位访问在没有LOCK前缀的x86上不是原子的)。 marshal/unmarshal要好得多,尽管前面的工作要多一些。
编组/解组的理念是将数据从一种格式转换为另一种格式,然后再将它们转换回来。这就是像Google Protocol Buffers,ZeroMQ这样的框架,以及许多其他框架以便携方式传输数据的方式。你基本上有专门的函数来获取你所说的“字符串”数据,并解析它,验证它,然后将它分配给你的结构。您会看到编组和序列化在许多情况下可以互换使用。
例如,在您的情况下,您可能拥有原型函数:
int
unmarshal_mystruct(const char *data, MyStruct &m);
在内部,您将解析data
中的数据,并填充m
。它确实变得乏味,这就是为什么这么多人使用框架的原因。
答案 1 :(得分:3)
使用序列化/反序列化代码。即例如,读入字节数组,然后将值转换为结构。这是多少框架(即CORBA等)。
缺点:要编写更多代码。
优点:更好的可移植性,LE / BE平台之间的兼容性。例如,您的代码可能无法在某些ARM设备上运行。
示例(struct):
typedef struct a
{
int a1;
int b2;
char cArray[5];
int c3;
} Mystruct;
写作:
void write_int(FILE *f, int value)
{
int32_t tmp = htonl(value); // write in BE form
fwrite(&tmp, 4, 1, f);
}
void a_write(Mystruct *d, FILE *f)
{
write_int(f, d->a1);
write_int(f, d->b2);
fwrite(d->cArray, 5, 1, f);
write_int(f, d->c3);
}
读:
void read_int(FILE *f, int *value)
{
int32_t tmp;
fread(&tmp, 4, 1, f);
*value = ntohl(tmp);
}
void a_read(Mystruct *d, FILE *f)
{
read_int(f, &d->a1);
read_int(f, &d->b2);
fread(d->cArray, 5, 1, f);
read_int(f, &d->c3);
}