1

I have the following structs in a C program.

typedef struct
{
  unsigned char msg_id : 8;
  unsigned char msg_num : 8;
} Message_Header_Type;
typedef struct
{
  Message_Header_Type header;
  int msg[32];
} Raw_Message_Type;

What I'm seeing is that the header in the Raw_Message_Type is taking up 4 bytes but I only want it to take only 2. How would I go about doing this?

1
  • 1
    If you pack the structure, you may be able to get Message_Header_Type down to 2 bytes -- but in Raw_Message_Type, header may still be followed by 2 bytes of padding so that the int array can be aligned on a 4-byte boundary. Commented Jul 19, 2016 at 20:07

4 Answers 4

3

What you are looking for is struct packing, which is platform and compiler dependent, the details are not specified in the C standard.

With GCC, on a 32-bit platform, you could do the following to get a struct of size 2:

typedef struct __attribute__((__packed__))
{
    unsigned char msg_id;
    unsigned char msg_num;
} Message_Header_Type;

From the GCC documentation:

packed This attribute, attached to an enum, struct, or union type definition, specified that the minimum required memory be used to represent the type.

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

2 Comments

I happen to like your approach more than mine, so I'm upvoting.
@JoshSanford Good to know about the pragma. +1
2

Message_Header_type inside of Raw_Message_Type is still taking 2 bytes as you would expect, but the compiler is padding the structure for alignment reasons, so your Raw_Message_Type is 132 bytes long instead of the 130 bytes you expected. This is probably because 32-bit aligned accesses are more efficient on your processor.

If you are using gcc, you can tell the compiler to align on 2-byte boundaries instead of the 4-byte boundaries that it is using by using #pragma pack.

typedef struct
{
  unsigned char msg_id : 8;
  unsigned char msg_num : 8;
} Message_Header_Type;
#pragma pack(push, 2) // save current alignment and set to 2-byte boundaries
typedef struct
{
  Message_Header_Type header;
  int msg[32];
} Raw_Message_Type;
#pragma pack(pop) // restore the previous alignment

Special packing like this is often necessary when using fixed-size structures in files, but be aware that there may be a (light) performance penalty for using a different packing than what the processor prefers. In this specific case, your 32 msg[] ints are now all 2 bytes off from the preferred alignment for your platform.

1 Comment

This worked. I am using Visual Studio so the "attribute" in other answers did not compile. But, I'm sure they will help others.
1

C implementations are free to insert padding into struct layouts between members, at the end, or both. It is common for them to do so for alignment purposes. It is also common for compilers to provide a mechanism to influence or override the padding, but details are necessarily implementation-specific.

With GCC, for example, you could apply the packed attribute to both your structs:

typedef struct __attribute__((__packed__))
{
  unsigned char msg_id : 8;
  unsigned char msg_num : 8;
} Message_Header_Type;

typedef struct __attribute__((__packed__))
{
  Message_Header_Type header;
  int msg[32];
} Raw_Message_Type;

Some other implementations borrow GCC's approach; some use pragmas for the same purpose; and some provide other mechanisms. You'll need to check your compiler's documentation.

Comments

0

Structure objects are not guaranteed the size of the sum of bits used in member bit fields. This is due to padding.

In your case though Raw_Message_Type has another member int msg[32];. It seems logical to use two more bytes for the purpose alignment so that msg[0] can be aligned to a 4-byte boundary.

There is a good chance that

Message_Header_Type obj;
printf("Size : %zu\n",sizeof(obj));

would give you 2 as a the result.

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.