4

考虑以下结构:

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++ 中类的成员变量执行相同的操作(从字符串填充)?如果是,如何?

4

2 回答 2

5

我强烈建议您购买并阅读Write Portable Code。你不想采用这种方法。不仅因为它不可移植(想想字节顺序问题),而且它确实会影响性能和原子性(非对齐的 32 位访问在没有 LOCK 前缀的 x86 上不是原子的)。编组/取消编组会好得多‌</a>​,尽管前面的工作要多一些。

编组/解组背后的想法是将您的数据从一种格式转换为另一种格式,然后再将它们转换回来。这就是像Google Protocol BuffersZeroMQ和许多其他框架这样以可移植的方式传输数据的方式。你基本上有专门的函数来获取你所说的“字符串”数据,你解析它,验证它,然后将它分配到你的结构中。您会看到编组和序列化在许多情况下可以互换使用。

例如,在您的情况下,您可能有一个带有原型的函数:

int
unmarshal_mystruct(const char *data, MyStruct &m);

在内部,您将解析来自 的数据data,然后填充m. 它确实变得乏味,这就是为什么这么多人使用这些框架的原因。

于 2013-04-15T10:13:12.197 回答
3

使用序列化/反序列化代码。例如,读入字节数组,然后将值转换为结构。这就是许多框架所做的(即 CORBA 等)。

缺点:要编写更多的代码。

优点:更好的可移植性,LE/BE 平台之间的兼容性。例如,您的代码可能无法在某些 ARM 设备上运行。

示例(结构):

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);
}
于 2013-04-15T10:02:42.620 回答