问题描述:

I want to parse a chunk of memory into a struct. The problem is that the members are not one after another and there is some padding.

struct foo {

unsigned int a; // @ 0

unsigned int junk; // @ 0x4

unsigned int b; // @ 0x08

unsigned int more_junk;

.........

};

I don't want to assign each member in the struct for every junk that I have. I know that this is possible with unions but not sure for structs.

Update

I'll make another more clear example:

#include <stdio.h>

#include <string.h>

main()

{

struct w {

unsigned long a;

unsigned long b;

unsigned long c;

unsigned long d;

};

struct w *q;

unsigned long array[] =

{

0x11111111,

0x22222222,

0x33333333,

0x44444444

};

q = (struct w*)array;

printf("%x\n", q->a);

printf("%x\n", q->b);

printf("%x\n", q->c);

printf("%x\n", q->d);

}

The output is:

11111111

22222222

33333333

44444444

Lets say that the 3's are junk. The same example:

#include <stdio.h>

#include <string.h>

main()

{

struct w {

unsigned long a;

unsigned long b;

unsigned long d;

};

struct w *q;

unsigned long array[] =

{

0x11111111,

0x22222222,

0x33333333,

0x44444444

};

q = (struct w*)array;

printf("%x\n", q->a);

printf("%x\n", q->b);

printf("%x\n", q->d);

}

The output is:

11111111

22222222

33333333

But it should be:

11111111

22222222

44444444

网友答案:

there is some padding.

Indeed. This is why structs are unsuitable and dangerous to use for memory mapping purposes.

The problem is that the members are not one after another I don't want to assign each member in the struct for every junk that I have

Not quite sure what you mean. You don't have to assign anything if you don't want to. You do however need to declare room for where the junk bytes will go. Simply declare a dummy variable in the struct which you later ignore, as you do in the very first struct example.

There is no way around this, the only alternative is to use an entirely different data structure such as a plain byte array of raw data. But that would hardly make your program easier to read.

However, if the junk bytes need not be preserved, i.e you are not doing a memory mapping but just some "cherry picking" of the data you are interested in, then you need no junk bytes in the struct. But you will have to assign every member manually, rather than using memcpy.

I know that this is possible with unions

No it isn't, I think you misunderstand how a union works.

网友答案:

From your question :

  1. Members are not one after another : I suggest you to rearrange the members of your struct so that they are in sync with the memory block you wish to copy.
  2. There is some padding : You can prevent the compiler from padding using __attribute__((__packed__)) keyword when you define your struct, which would direct compiler to stop padding.
struct  __attribute__((__packed__)) foo {
    unsigned int a; // @ 0
    unsigned int junk; // @ 0x4
    unsigned int b; // @ 0x08
    unsigned int more_junk;
    .........
};

After this you can either use memcpy() to copy the contents of the memory block to the struct foo variable or if it is struct foo *ptr then directly point to the memory.

For more info on struct padding and packing refer : structure padding and structure packing

相关阅读:
Top