Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__attribute__((packed)) alternative

consider the following structure:

typedef struct __attribute__((packed)) a{
    int a1;
    int b2;
    char cArray[5];
    int c3;
} Mystruct;

Now in my code, Im doing this:

char source[50];
Mystruct mm;
//...
//initialization and other codes
//...
memcpy(&mm,source,sizeof(mm));

I am trying to fill up the structure from a string (from a file to be more specific), and hence I don't want the padding. But think packing affects the performance also.

So my question is, is there any other way to accomplish what I want?
Is it possible to do the same (filling up from a string) with member variables of a class in c++? If yes, how?

like image 498
Dipto Avatar asked Feb 16 '23 19:02

Dipto


2 Answers

I'd highly recommend you purchase and read Write Portable Code. You don't want to take this approach. Not only because it isn't portable (think endianess issues), but it does impact performance and atomicity (non-aligned 32-bit access is not atomic on x86 without a LOCK prefix). It's much better to marshal/unmarshal‌​, even though it's a bit more work up front.

The idea behind marshaling/unmarshaling is to convert your data from one format to another, and them back again. This is what frameworks like Google Protocol Buffers, ZeroMQ, and many others do to transfer data in a portable way. You basically have specialized functions that take your "string" data that you spoke of, and you parse it, validate it, and then assign it into your structure. You'll see marshaling and serialization used interchangeably in many contexts.

For instance, in your case, you might have a function with the prototype:

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

Internally, you'd parse the data from data, and populate m. It does get tedious which is why so many people use the frameworks.

like image 156
John Szakmeister Avatar answered Feb 19 '23 09:02

John Szakmeister


Use serialization/deserialization code. I.e. read into byte array, for example, and then convert values into structure. This is how many frameworks do (i.e. CORBA etc).

Drawbacks: more code to write.

Benefits: better portability, compatibility between LE/BE platforms. For example, you code may not work on some ARM devices.

Example (struct):

typedef struct a
{
    int a1;
    int b2;
    char cArray[5];
    int c3;
} Mystruct;

Writing:

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

Reading:

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);
}
like image 27
Valeri Atamaniouk Avatar answered Feb 19 '23 10:02

Valeri Atamaniouk