3

I have a representation of an IP header in C with bit-precision fields:

typedef struct __attribute__((packed)) {
    unsigned char __reserved : 1;
    unsigned char dont_fragment : 1;
    unsigned char more_fragment : 1;
    unsigned short fragment_offset : 13; // if fragmented, in 8 byte units from the start of the datagram
} ipv4_fragmenting;

I use 16 bits that can be stored on 2 bytes. So why is the size of the structure (sizeof(ipv4_fragmenting)) is 4 instead of 2?

My compiler: GCC 4.8.1

Edit:

If bitfields are so platform-specific and packed attribute is unreliable what would be the correct solution to represent elements of previously defined protocols like IPv4?

7
  • The language doesn't guarentee the size of a data type exactly. It only guarentees their minimum, hence speculating on implementation-defined behaviour is moot. Commented Feb 10, 2014 at 12:18
  • possible duplicate of Why isn't sizeof for a struct equal to the sum of sizeof of each member? Commented Feb 10, 2014 at 12:21
  • My gcc 4.6.3 on 64 bit linux with default settings compiles this to a 2B struct. Commented Feb 10, 2014 at 12:21
  • 2
    Maybe a bug in gcc 4.8? Commented Feb 10, 2014 at 12:22
  • 1
    Bit-fields are packed dependent on the target platform and the compiler. This may vary from e.g., i386 and ARM. Some CPUs requires words (16 bit) to be aligned on even addresses and some does not, etc. Use only bit-fields for internal data-structures and not to build protocol messages. Commented Feb 10, 2014 at 12:57

4 Answers 4

2

Like I've already commented, speculating on bit field and structure size is moot since the language doesn't mandate anything in this area.

As for the size being 4 on GCC 4.8.1 (assuming a 32-bit compiler); this is perhaps a bug on GCC 4.8.1. I've raised a question on SO previously where setting the packed attribute doesn't work as expected, like here. For a byte aligned packing only using #pragma pack works. Example:

#include <stdio.h>

#pragma pack(push, 1)
typedef struct {
    unsigned char __reserved : 1;
    unsigned char dont_fragment : 1;
    unsigned char more_fragment : 1;
    unsigned short fragment_offset : 13; // if fragmented, in 8 byte units from the start of the datagram
} ipv4_fragmenting;
#pragma pack(pop)

int main()
{
    printf("%u\n", sizeof(ipv4_fragmenting));
}

This prints 3 for me, as expected on a ILP32 machine MinGW GCC 4.8.1.

Sign up to request clarification or add additional context in comments.

3 Comments

I haven't use #pragma pack, but why is the expected size is 3?
short on an ILP32 machine would be 2 bytes, the remaining three 1-bit fields can be packed into a single byte, leading to 3 bytes. As for why it doesn't pack tighter than this, I don't've a clear answer, since they're bit-fields.
because 16bit values must be stored on a 16bit boundary, 32bit on a 32bit boundary etc...
1

Bit field storage is implementation dependent. The fields that you have defined may be padded (increasing the storage required).

2 Comments

Primitive data type storage itself is implementation-defined let alone bit-fields :)
But I explicitly asked for my fields to be packed, which means that they should not be padded.
0

On some 32bit platforms structures are padded to be on 32 bit boundaries, eg. every 4 bytes. On GCC I think you can control this on some platforms see: Structure Packing Pragmas

2 Comments

I have an other (bit-field) structure, that has a size of 1 byte. So this cannot be the source of the problem.
It context sensitive, for example if you have a structure which has a 1 byte bit-field followed by a char, and a short that packs to 32 bits you would not see it.
0

I've always read that type sizes depends on the implementation and architecture and the OS. I don't think it's a bug. Anyway, you must trust on your sizeof function, as this will tell you your particular truth.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.