0
votes

My question is based off a part of this wiki answer to the question of Why isn't sizeof for a struct equal to the sum of sizeof of each member? (emphasize mine):

"IMPORTANT NOTE: Both the C and C++ standards state that structure alignment is implementation-defined. Therefore each compiler may choose to align data differently, resulting in different and incompatible data layouts. For this reason, when dealing with libraries that will be used by different compilers, it is important to understand how the compilers align data. Some compilers have command-line settings and/or special #pragma statements to change the structure alignment settings."

  • Is it possible to detect and change the current structure alignment setting in gcc/g++?
  • And if so, How do I detect the current alignment setting + how can I change it in gcc/g++?

Thank you very much for your help.

2
Just specify the alignment explicitly with __attribute__ ((aligned (x))) so no need to detect anything.Eugene Sh.
Pretty sure it's about __attribute__((packed)) (which should be banned).EOF
@EugeneSh. because they have to think about the order of their struct members? Because they prefer torturing their load/store units in the microprocessor to make up for tiny amounts of memory?EOF
@EugeneSh. __attribute__((packed)) is not an adequate substitute for proper serialization.EOF
@RobertSsupportsMonicaCellio Write a function that serializes your data into a uint8_t-array. Better yet, define a grammar for the serialized format, autogenerate the code, for both serializing and deserializing, so you don't have any mismatch, neither between serializing and deserializing, nor among different architectures.EOF

2 Answers

2
votes

Is it possible to ... change the current structure alignment setting in gcc/g++?

Yes. GCC pragmas and command line options are described in GCC documentation.

There is a command line option:

-fpack-struct[=n]

Without a value specified, pack all structure members together without holes. When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment (that is, objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location.

Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it makes the code suboptimal. Use it to conform to a non-default application binary interface.

And pragmas:

For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives which change the maximum alignment of members of structures (other than zero-width bitfields), unions, and classes subsequently defined. The n value below always is required to be a small power of two and specifies the new alignment in bytes.

  1. #pragma pack(n) simply sets the new alignment.
  2. #pragma pack() sets the alignment to the one that was in effect when compilation started (see also command line option -fpack-struct[=] see Code Gen Options).
  3. #pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.
  4. #pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).

Some targets, e.g. i386 and powerpc, support the ms_struct #pragma which lays out a structure as the documented __attribute__ ((ms_struct)).

  1. #pragma ms_struct on turns on the layout for structures declared.
  2. #pragma ms_struct off turns off the layout for structures declared.
  3. #pragma ms_struct reset goes back to the default layout.

Is it possible to detect ... the current structure alignment setting in gcc/g++?

Depends a lot on what you mean by "detect". There is following command line option:

-frecord-gcc-switches

This switch causes the command line that was used to invoke the compiler to be recorded into the object file that is being created. This switch is only implemented on some targets and the exact format of the recording is target and binary file format dependent, but it usually takes the form of a section containing ASCII text.

If such option was used, then you can detect whether -fpack-struct[=n] was used by inspecting the binary.


If you simply want to know the alignment of a particular type, you can use the alignof operator. If you want to know the maximum alignment of any scalar type, you can use alignof(std::max_align_t). You can specify classes or arrays to have stricter alignment than they would otherwise have with alignas. If that exceeds the alignment of std::max_align_t, then the class is said to be over-aligned.

1
votes

For C++, starting in C++11 you can use alignas and alignof to portably set and get the alignment of any type. Below is the example from cppreference for alignof where you can see both in action:

#include <iostream>

struct Foo {
    int   i;
    float f;
    char  c;
};

struct Empty {};

struct alignas(64) Empty64 {};

int main()
{
    std::cout << "Alignment of"  "\n"
        "- char             : " << alignof(char)    << "\n"
        "- pointer          : " << alignof(int*)    << "\n"
        "- class Foo        : " << alignof(Foo)     << "\n"
        "- empty class      : " << alignof(Empty)   << "\n"
        "- alignas(64) Empty: " << alignof(Empty64) << "\n";
}

Possible output:

Alignment of
- char             : 1
- pointer          : 8
- class Foo        : 4
- empty class      : 1
- alignas(64) Empty: 64

It should be noted that alignas won't let you use an alignment that is less strict then what the object would need by default. This means you can't use it to "pack", remove the padding, of a data structure.