1

In the following 2 structures,

typedef struct _a {
    short a1:13 __attribute__((packed));
    char a2[4]  __attribute__((packed));
} a;

typedef struct _b {
    short b1:10 __attribute__((packed));
    short b2:10 __attribute__((packed));
    short b3:12 __attribute__((packed));
} b;

In struct b, I find that bits of b2 are packed with b1, and bits of b3 are packed with b2. It ultimately results in 4 byte value.

I was expecting the similar behaviour with struct a but I don't see the same. First 2 bytes are occupied with a1 (unused 5 bits) and following by 4 bytes for a2.

Is this behaviour expected? Why can't I pack the char[4] along with short:13? Is there a way to achieve it?

alk
  • 69,737
  • 10
  • 105
  • 255
badmad
  • 2,059
  • 2
  • 14
  • 14
  • This is not valid C code but some non-standard extension. Therefore, nobody can answer your question unless you state which compiler you are using. – Lundin Dec 06 '12 at 07:47
  • What is invalid about it? I am on a standard linux box with gcc (GCC) 4.1.2 20071124 (Red Hat 4.1.2-42). – badmad Dec 07 '12 at 02:44
  • @badman `__attribute__((packed))` is not standard C. – Lundin Dec 07 '12 at 07:22

2 Answers2

8

a2 is not a bit-field so it will never be put together with a1. The standard says

Values stored in non-bit-field objects of any other object type consist of n × CHAR_BIT bits, where n is the size of an object of that type, in bytes. The value may be copied into an object of type unsigned char [n] (e.g., by memcpy); the resulting set of bytes is called the object representation of the value.

So such a sub-object must be an addressable unit, and there is not exception possible from that rule.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Thank you! You say that it's never possible which is acceptable because it is designed like that. I am trying to understand the reason for that. Why is there a restriction that the sub-object must be an addressable unit? Compiler should be able to figure out what my intention is. It doesn't sound very complex. Would you know why this restriction comes from? – badmad Dec 07 '12 at 02:42
  • @badmad, it is just simple, a type is supposed to be compatible across compilation units, all types that declare the same types of fields in the same order *must* behave the same. So the compiler cannot deduce that in no other compilation unit the address of such a wouldn't be taken. The idea of types is to define interfaces. And BTW, your first example is even such that the address must be usable. You define it as an array, in C the only reasonable way to use such a component is to use it in expressions that implicitly take the start address of that array. – Jens Gustedt Dec 07 '12 at 06:21
  • Acceptable explanation, Jens! Thanks a lot! – badmad Dec 09 '12 at 01:06
1

(Too long to be a comment, so i put it as an answer)

To pack all fields together, you must replace the array with 4 fields:

typedef struct _a {
    short a1:13 __attribute__((packed));
    char a2_0:8 __attribute__((packed));
    char a2_1:8 __attribute__((packed));
    char a2_2:8 __attribute__((packed));
    char a2_3:8 __attribute__((packed));
} a;
anatolyg
  • 26,506
  • 9
  • 60
  • 134