Search Flipkart

Friday, November 6, 2015

Where to use structure packing in Embedded C?

What is structure padding?


Before understanding about structure packing, let's see what is structure padding.

In order to align the data in memory,  one or more empty bytes (addresses) are inserted (or left empty) between memory addresses which are allocated for other structure members while memory allocation. This concept is called structure padding.
Architecture of a computer processor is such a way that it can read 1 word (4 byte in 32 bit processor) from memory at a time.
To make use of this advantage of processor, data are always aligned as 4 bytes package which leads to insert empty addresses between other member’s address.
Because of this structure padding concept in C, size of the structure is always not same as what we think.

So, We can say that, padding aligns structure members to "natural" address boundaries.
Padding is on by default. It inserts the following "gaps" into your first structure:

Unaligned memory access is slower on architectures that allow it (like x86 and ARM), and is explicitly prohibited on strict alignment architectures like SPARC.

struct struct_A {
    char a;
    char gap_0[3]; /* inserted by compiler: for alignment of b */
    int b;
    char c;
    char gap_1[3]; /* inserted by compiler: for alignment of the whole struct in an array */
} x;

See this link for more insight on structure padding.

What is structure packing?


Packing, on the other hand prevents compiler from doing padding - this has to be explicitly requested.
As mentioned earlier, when you are working with ARM architecture, you can use unaligned access. That means that it supports PACKING. 

In Linux, you can see following declaration:

struct __attribute__((__packed__)) struct_A {
    char a;
    int b;
    char c;
};

Under GCC, it's __attribute__((__packed__)) , that is used to explicitly request packing, to prevent compiler from doing padding.

But why we need packing? It prevents padding, which may lead to unaligned memory whose access is slower. Why we need it?

While I was working on a project in Bluetooth driver, in which, the BT HCI transport layer driver (lower layer of BT stack) needed to be ported from Linux to WEC2013 (WinCE).

I came across __attribute__((__packed__)) declarations in Linux code.
This is not supported in WinCE as is. If we ignore this, compiler will pad the structure, by default.

Why did they pack the structure?

If we don't pack this structure, compiler will add "gap" or "dummy bytes" for padding the structure, which will result in increasing the size of structure.
In this particular code, the structure will be sent to BT module (firmware running on module) as buffer. So, the structure should be sent as is, and any extra bytes added in-between will result in error.

That is, If the structure is padded, BT module (firmware running on module) will get altered value, so it won't work!

This is one of the case, where structure packing is a must. We should explicitly tell the compiler that it shouldn't add extra bytes to structure.

How to pack the structure in WinCE?

In WinCE, we should use #pragma directive to instruct the compiler how to pack a structure.

Note: #pragma gives the compiler special instructions for the compilation of the file in which it appears.

We need to do the following to pack the structure in WinCE:

# pragma pack (1)
struct struct_A
{
    char a;
    int b;
    char c;
} x;
# pragma pack ()





Leave your questions or suggestions in comment box.
Thanks.

No comments:

Post a Comment