__attribute __((packed))替代

时间:2013-04-15 09:51:06

标签: c++ c padding packed

考虑以下结构:

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

2 个答案:

答案 0 :(得分:5)

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

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

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

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