Re: "common initial sequence" rule = non-obvious constraints on padding?



"Tom Yu" <tlyu@xxxxxxx> wrote in message news:ldv63xsced6.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
C99 6.5.2.3p5 allows a program to inspect the "common initial sequence"
of any member struct of a union which currently contains such a struct
object, anywhere that union type is visible. This effectively
requires that the layout of a struct be determined entirely by the
ordering and types of its members, and not by its member names or its
tag.

If by "effectively" you mean on any "normal" implementation, then yes. But I'm sure that on the DS9000, the linker searches the complete program for unions and adds random padding between structure members in a way that breaks this assumption.

not be apparent from reading 6.2.7, which says that two structure
types are not compatible types unless each pair of corresponding
members is declared with compatible types and with the same names, in
addition to being required to be declared with the same tag name.

Type compatibility is not just about memory layout; if two types are compatible, you can declare the same object twice, using both types, without breaking the program. I think it's a good thing that the standard forbids objects whose members have different names in different translation units.

This text in 6.2.7, along with a general (probably intentional) lack
of specificity concerning structure padding, suggests that an
implementation is free to (admittedly perversely) vary the padding of
a struct depending on what names the members have and what the tag
name of the struct is. If two structs were declared in the same
translation unit and were identical except for the naming of their
members and their tags, such an implementation would be free to make
them have different padding from each other... unless there were
somewhere in the translation unit the declaration of a union type
containing both as members.

Or some other requirement forbids them to have different padding, as your own example demonstrates.

[example snipped]

This leads me to conclude:

(1) The struct compatibility rules in 6.2.7 apply solely to place
limits on possible aliasing, and do not give an implementation
license to vary the layout of a struct based on its tag name or
its element names.

Compatibility od types servers various purposes; one of them is to place limits on the differences between allowed declarations the same object. It would be a bad idea to let programs declare the same object to be a "struct { int a; float b; }" in one translation unit, and a "struct { int b; float a; }" in another.

(2) The layout of a struct can only depend on the ordering and types
of its elements.

An implementation is not required to make the final determination of the layout of each structure separately for each translation unit. It's conceivable that an interpreter, or an implementation with a "smart" optimizing linker, could defer decisions about how to pad structures until it has seen the complete program. It doesn't sound very practical to make the layout depend on the names of members, but adjusting the padding between initial members based on how big the structure is, or what kind of alignment requirements are imposed by other members, sounds quite reasonable to me, provided that the compiler has a way to tell the smart linker which structures must be kept in sync because they're members of a union declared somewhere in the complete program.

I believe some of the Committee's responses to Defect Reports provide
some corroboration for (1). Did the Committee intend for (2) to be a
requirement? If so, why is it not stated more clearly in the
Standard?


.



Relevant Pages

  • Re: bitwise on float
    ... union kludge { ... You can then store a double value in the "d" member, ... Well, if you're going to declare it like that, then apparently writing ... struct double_rep { ...
    (comp.lang.c)
  • Re: Global (non _KERNEL) place for sockaddr_union?
    ... The problem is that the definition of the union depends on what you wish ... and which address families are visible to the application ... You may find that such a definition has to have conditionalized members. ... type 'struct sockaddr_storage' if it's to support all address families ...
    (freebsd-arch)
  • Re: Global (non _KERNEL) place for sockaddr_union?
    ... The problem is that the definition of the union depends on what you wish ... and which address families are visible to the application ... You may find that such a definition has to have conditionalized members. ... type 'struct sockaddr_storage' if it's to support all address families ...
    (freebsd-hackers)
  • Re: Global (non _KERNEL) place for sockaddr_union?
    ... The problem is that the definition of the union depends on what you wish ... and which address families are visible to the application ... You may find that such a definition has to have conditionalized members. ... type 'struct sockaddr_storage' if it's to support all address families ...
    (freebsd-net)
  • Re: Unions and Structure Questions
    ... >>Whereas the members of a struct each occupy a different memory location, ... > Plus the size of any padding between the members and after the last ... I would not expect any padding in a union, unless two or more members have ...
    (alt.comp.lang.learn.c-cpp)