1

Lets take a look at the following structs:

struct child {
    int a:1;
    int b:2;
    int c:2;
} __attribute__((packed));

struct parent1 {
    int x:3;
    struct child y;
} __attribute__((packed));

struct parent2 {
    int p:1;
    int q:5;
    int r:5;
    struct child s;
} __attribute__((packed));

These are the sizes I am getting:

sizeof(int)             4
sizeof(struct child)    1
sizeof(struct parent1)  2
sizeof(struct parent2)  3

I've heard that padding is added before structs for performance reasons. But forgetting about performance for a moment, is there a way so that I can get the following sizes?

sizeof(struct parent1)  1
sizeof(struct parent2)  2

As only that much of memory is actually required...


EDIT

Is there any way of doing it with gcc on linux?

Akshdeep Singh
  • 1,301
  • 1
  • 19
  • 34
  • Does this answer your question? [Size of structure with bit fields](https://stackoverflow.com/questions/24725188/size-of-structure-with-bit-fields) – Hitokiri May 15 '20 at 20:22
  • And https://stackoverflow.com/questions/4129961/how-is-the-size-of-a-struct-with-bit-fields-determined-measured – Hitokiri May 15 '20 at 20:22
  • @Hitokiri they don't answer my questions, I haven't asked how size of such structs are calculated, I've asked how can I change my code, so that they only take space as much is required... – Akshdeep Singh May 15 '20 at 20:24
  • 1
    No, you can't. `struct child` can't be smaller than `1`. – Eugene Sh. May 15 '20 at 20:27
  • @EugeneSh. So can I do something else? I just want to common out some bitfields from parent structs... – Akshdeep Singh May 15 '20 at 20:29
  • 1
    Then accept the sizes it gives you. Are you short on memory? – Eugene Sh. May 15 '20 at 20:30
  • I don't want padding, I want continuous memory, just experimenting with C what I can, and what I can't... – Akshdeep Singh May 15 '20 at 20:32
  • You can always just use an array and handle the `&` `|` work yourself if the compiler gets in your way. I may be too old school, but I don't trust a compiler to get the input perfect with bitfields due to padding, byte order, and such. – Michael Dorgan May 15 '20 at 20:40
  • 1
    You can do almost anything with C, it's just that sometimes it will be ugly, non-portable or awkward. – Eugene Sh. May 15 '20 at 21:05
  • Recommendation: avoid bitfields altogether, especially if you care about the size or layout details of your structures. There are many fewer guarantees about bitfields than people tend to assume, and on the other hand there are some potentially surprising constraints. They are very hard to use portably, and there are things they won't do even if you don't care about portability. – John Bollinger May 15 '20 at 21:28

2 Answers2

0

No it is not possible to pack structures tighter than what your compiler does.

Every struct must start on a byte boundary, so the members s and y cannot use the available bits from the previous members of their enclosing struct definition.

Also note that __attribute__((packed)) is an extension that might not be supported on many compilers.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

If all else fails, you can always write functions and macros to bitshift & extract what you need.

Using unions gets close to what you want. It may be possible to use C++ to clean up the syntax, but with C, this is the closest (non-bitwise) solution I could come up with: (note parent1 is near perfect.)

#pragma pack(1)
typedef struct {
  char x:3;
  char a:3;
  char b:3;
  char c:3;
} child;

typedef union {
  char x:3;
  child y;
} parent1;

typedef struct {
  short p:1;
  short q:5;
  short r:5;
  short s:5;
} par2;

typedef struct {
  char pad;
  child s;
} padchild;

typedef union {
  par2 parent2;
  padchild s;
} parent2;

#pragma pop

Technically unions are for either-or use and compilers can pad however they want, but by forcing the bit counts to be the same, easiest way for the compiler to implement happens to be what you want.

Abel
  • 111
  • 4