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?

Boldizsár Németh
  • 1,847
  • 13
  • 20
  • 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. – legends2k Feb 10 '14 at 12:18
  • possible duplicate of [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) – Klas Lindbäck Feb 10 '14 at 12:21
  • My gcc 4.6.3 on 64 bit linux with default settings compiles this to a 2B struct. – Petr Skocik Feb 10 '14 at 12:21
  • 2
    Maybe a bug in gcc 4.8? – Petr Skocik Feb 10 '14 at 12:22
  • @KlasLindbäck The suggested question is C++ and packed attribute is not used. – Boldizsár Németh Feb 10 '14 at 12:30
  • @BoldizsárNémeth The suggested duplicate is marked both C and C++ and is valid for both languages. However, regarding your Edit; struct packing is platform dependent and I don't think there is a platform independent way to declare structs with packing. – Klas Lindbäck Feb 10 '14 at 12:56
  • 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. – Jens Schwarzer Feb 10 '14 at 12:57

4 Answers4

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.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • I haven't use #pragma pack, but why is the expected size is 3? – Boldizsár Németh Feb 10 '14 at 12:27
  • `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. – legends2k Feb 10 '14 at 12:29
  • 2
    because 16bit values must be stored on a 16bit boundary, 32bit on a 32bit boundary etc... – AnthonyLambert Feb 10 '14 at 16:25
1

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

bblincoe
  • 2,393
  • 2
  • 20
  • 34
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

AnthonyLambert
  • 8,768
  • 4
  • 37
  • 72
  • I have an other (bit-field) structure, that has a size of 1 byte. So this cannot be the source of the problem. – Boldizsár Németh Feb 10 '14 at 12:20
  • 1
    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. – AnthonyLambert Feb 10 '14 at 12:23
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.

Javier
  • 801
  • 3
  • 10
  • 24