0

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
selfbg
  • 317
  • 1
  • 4
  • 14
  • In memory, are the values for `a` and `b` adjacent, or separated by the gap for `junk`? – JS1 Nov 13 '14 at 11:18
  • There is a gap. All my members are unsigned long. Also the gap is not always even. – selfbg Nov 13 '14 at 11:23
  • @selfbg Since your question is really unclear about the format of your data source, all answers are shooting in the dark. But from what I can gather, assigning each member manually is the only sensible way to do it. – user694733 Nov 13 '14 at 11:27
  • @user694733 I've made edited the question. Hope this is more clear. – selfbg Nov 13 '14 at 12:01
  • 1
    @selfbg That makes it clear. Unfortunately is was right; only sensible and portable way to do what you want, is to assign members manually (`struct w s; s.a = array[0]; s.b = array[1]; s.d = array[3];`). – user694733 Nov 13 '14 at 12:19

3 Answers3

1

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

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 packing

Community
  • 1
  • 1
Santosh A
  • 5,173
  • 27
  • 37
0

Hi friend in GCC you can using this in struct for padding :

Type : Width;

this variable hasn't name;

struct foo {
    unsigned int a: 4;
    unsigned int: 4; //junk;
    unsigned int b: 1;
    unsigned int: 7; //more_junk;
};

this struct uses 2 byte of sram memory.

FOR your example:

main() {

    struct w {
        unsigned long a;
        unsigned long b;
        unsigned long;
        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);

}
Răzvan Petruescu
  • 685
  • 1
  • 8
  • 16