1

There are various pragmas for controlling the struct/class layout, such as pragma pack. But as far as I know, there's no pragma for saying "I don't care about the layout. It's internal, the code doesn't rely on it. Reorder it for best performance/size.". AFAIK, that's the typical case, and it could improve performance/size in many cases. Also, even if the programmer was careful enough to reorder it for performance/size, a different target architecture might have a different optimal layout.

Edit: to clarify, I'm talking about the order of members. Padding is already controllable.

Also, PVS-Studio has a relevant message. That's what I'm talking about - why can't this be done by a compiler with a pragma?

Paul
  • 6,061
  • 6
  • 39
  • 70
  • Do you mean something that would allow to, say, re-order the data members? – juanchopanza Oct 16 '14 at 15:41
  • @juanchopanza: Seems like Paul is asking about padding. – John Dibling Oct 16 '14 at 15:49
  • @juanchopanza, yes, added a clarification. – Paul Oct 16 '14 at 15:53
  • 1
    This question is ill specified because neither C nor C++ say anything about `pragma`. Perhaps the compiler that you are using has some implementation specific details, but they would be specific to that compiler. – David Heffernan Oct 16 '14 at 15:57
  • As @MarkB said: the language specifies the relative order of struct elements in memory. A compliant compiler may not reorder them. For C (as opposed to C++) elements are ordered in memory strictly in the order they are declared (with some complications related to bitfields). – John Bollinger Oct 16 '14 at 15:58
  • 1
    I thought `pragma`s can go against the specification? e.g. `__declspec(novtable)`, I don't think it's allowed by the spec. – Paul Oct 16 '14 at 16:01
  • 1
    This exists, it is just not a common feature in C or C++ compilers. .NET does this for example, the CLR optimizes the layout of an object and reorders members to get the smallest possible layout. But it also enforces this at runtime, the layout is undiscoverable and mapping to a defined layout requires marshaling. The C/C++ way is to make this a programmer's job. – Hans Passant Oct 16 '14 at 16:09
  • 1
    Some old versions (perhaps 4.4 or 4.5) of GCC had an optimization pass to reorder members of `struct`-s, but that did not work always well and was removed later. – Basile Starynkevitch Oct 16 '14 at 17:38

2 Answers2

2

The language specifically calls out that class members will be ordered in memory the same way they are in each access level (like private). There is no way a pragma could override this behavior.

See 9.2/14:

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified

Bear in mind that reordering members changes the order in which sub-object constructors and destructors would be called, and possibly other things. It seems extremely risky even given a pragma for the compiler to make these sorts of changes behind the scenes (what if you have a member that depends on the initialization of another member).

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 1
    Note for example the two attributes in this answer: http://stackoverflow.com/a/11770476/47453 Both of those change the structure layout in a manner that is barred by the C and C++ standards. But they still exist. They just cause non-standard behavior. – Bill Lynch Oct 16 '14 at 16:08
  • I thought it was the order they are declared in the class, regardless of access level. – Neil Kirk Oct 16 '14 at 16:17
  • @neilkirk That was my understanding as well - `private` `public` and `protected` are purely high-level concepts that are essentially well-enforced (and easily-circumvented) hints to other programmers. – fluffy Oct 16 '14 at 16:24
  • The answer is correct. Rearrangement of blocks with different access levels is allowed. – Jerry Coffin Oct 16 '14 at 17:39
1

Such a pragma would be permitted by the language standard, but I'm not aware of any compiler that implements such a thing.

In C, the behavior of #pragma is specified in section 6.10.6 of the standard (the link is to the latest draft):

A preprocessing directive of the form
# pragma pp-tokensopt new-line
where the preprocessing token STDC does not immediately follow pragma in the directive (prior to any macro replacement) causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner. Any such pragma that is not recognized by the implementation is ignored.

So a #pragma can, in effect, violate the rules of the language.

The relevant rule in this case is that struct members are laid out in the order in which they're declared. 6.7.2.1 paragraph 15:

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

The bad news: The C standard requires struct members to be laid out in the order in which they're declared. The first member must be at offset 0. There may be arbitrary padding between members, or after the last one, but they cannot be reordered.

The good news: The language permits an implementation to define a #pragma that specifies a layout that violates the above rule.

The bad news: As far as I know, no implementation actually does so. Even if one did, there are other implementations that do not, so any code that uses such a #pragma would be non-portable. (Though at least if the name of the #pragma is unique, any compilers that don't recognize it are required to ignore it, so your code would still compile.)

That's for C. The C++ rules for #pragma are very similar to the C rules. I'm reasonably sure the C++ rules for struct layout are also similar to C's; inheritance makes things a little more complex.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631