0

In C, sometimes certain members of a structure tend to have misaligned offsets, as in case of this thread in HPUX community

In such a case, one is suggested to use zero-width bit field to align the(misaligned) next member. Under what circumstance does misalignment of structure members happen? Is it not the job of the compiler to align offsets of members at word boundary?

Phalgun
  • 1,181
  • 2
  • 15
  • 42
  • 1
    Please cite your sources. ("one is suggested"? By whom?). It is the job of the compiler to correctly align members as necessary, and compilers do so well. So there is no tendency to have misaligned offsets. – rici May 14 '14 at 20:13
  • @rici Well I was following up on a question in [HPUX community](http://goo.gl/klU4Nd) for a Core dump generated due to misaligned member of a structure. You can see that it does happen and people do get bugged with it. – Phalgun May 14 '14 at 20:27
  • @ZanLynx, I did look at that thread before posting, and it does not answer my question as to why do compilers not align only certain members of the structure. – Phalgun May 14 '14 at 20:33
  • Compilers automatically give struct members whatever alignment they need. The code in the thread you refer to may have been incorrectly assuming stricter alignment than the members actually require. – Keith Thompson May 14 '14 at 20:43
  • @Phalgun: Please edit your question to include that link. Otherwise it is *very* difficult to know what you're talking about. – rici May 14 '14 at 20:52
  • voted to reopen because the linked question is about zero-length bit-fields, whereas this question is about circumstances under which a struct member might need explicitly specified alignment. IMHO the linked question is effectively an XY question, rather than a response. – rici May 15 '14 at 17:43
  • @ncl: I haven't looked but I suspect that just changes which question this is a duplicate of. – Zan Lynx May 16 '14 at 00:14
  • @ncl: oh yeah...there's 1,205 search results for [c] structure alignment. probably an entire week's project to clean that up. – Zan Lynx May 16 '14 at 00:17

2 Answers2

4

"Misalignment" of a structure member can only occur if the alignment requirements of the structure member are deliberately hidden. (Or if some implementation-specific mechanism is used to suppress alignment, such as gcc's packed attribute`.)

For example, in the referenced problem, the issue is that there is a struct:

struct {
    // ... stuff
    int               val;
    unsigned char     data[DATA_SIZE];
    // ... more stuff
}

and the programmer attempts to use data as though it were a size_t:

*(size_t*)s->data

However, the programmer has declared data as unsigned char and the compiler therefore only guarantees that it is aligned for use as an unsigned char.

As it happens, data follows an int and is therefore also aligned for an int. On some architectures this would work, but on the target architecture a size_t is bigger than an int and requires a stricter alignment.

Obviously the compiler cannot know that you intend to use a structure member as though it were some other type. If you do that and compile for an architecture which requires proper alignment, you are likely to experience problems.

The referenced thread suggests inserting a zero-length size_t bit-field before the declaration of the unsigned char array in order to force the array to be aligned for size_t. While that solution may work on the target architecture, it is not portable and should not be used in portable code. There is no guarantee that a 0-length bit-field will occupy 0 bits, nor is there any guarantee that a bit-field based on size_t will actually be stored in a size_t or be appropriately aligned for any non bit-field use.

A better solution would be to use an anonymous union:

// ...
int             val;
union {
  size_t        dummy;
  unsigned char data[DATA_SIZE];
};
// ...

With C11, you can specify a minimum alignment explicitly:

// ...
int                            val;
_Alignas(size_t) unsigned char data[DATA_SIZE];
// ...

In this case, if you #include <stdalign.h>, you can spell _Alignas in a way which will also work with C++11:

int                            val;
alignas(size_t) unsigned char data[DATA_SIZE];
rici
  • 234,347
  • 28
  • 237
  • 341
  • Thanks for your explanation @rici. However, I would like to add an excerpt from C99 standard, "As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bit-field, if any, was placed" Does this not indicate that zero-width bit-fields should be portable? – Phalgun May 15 '14 at 06:28
  • @Phalgun: The quote says exactly what it says and no more. Read the paragraph before: "An implementation may allocate any addressable storage unit large enough to hold a bitfield... The alignment of the addressable storage unit is unspecified." So there is no guarantee about alignment or size; only that two bitfields separated by a zero-length bitfield are not in the same addressable storage unit. That doesn't affect the alignment of a following `char` array, since there is no following bitfield and even if there were, it would not have a defined alignment. – rici May 15 '14 at 14:20
1

Q: Why does it misalignment happen? Is it not the job of the compiler to align offsets of members at word boundary?

You are probably aware that the reason that structure fields are aligned to specific boundaries is to improve performance. A properly aligned field may only require a single memory fetch operation by the CPU; where a mis-aligned field will require at least two memory fetch operations (twice the CPU time).

As you indicated, it is the compilers job to align structure fields for fastest CPU access; unless a programmer over-rides the compiler's default behavior.

Then the question might be; Why would the programmer over-ride the compiler's default alignment of structure fields?

One example of why a programmer would want to over-ride the default alignment is when sending a structure 'over the wire' to another computer. Generally, a programmer wants to pack as much data as possible, into fewest number of bytes.

Hence, the programmer will disable the default alignment when structure density is more important than CPU performance accessing structure fields.

Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
  • It's worth noting that not all CPU's will only suffer performance degradation. Some, eg Sparc will core dump on a non-aligned access. – camelccc May 14 '14 at 21:04