Topic: Padding guarantees for structs?
Author: bparker@uq.net.au (Brian Parker)
Date: 1999/06/23 Raw View
On 16 Jun 99 17:12:14 GMT, James.Kanze@dresdner-bank.com wrote:
>In article <7k7l4o$n0r$1@mulga.cs.mu.OZ.AU>,
> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote:
>
>> It's true that the standard allows padding bits in this situation,
>> but I don't think they are "likely" -- off-hand, I don't know of any
>> implementation which inserts padding bits in that situation, and my
>guess
>> is that only implementations for obscure architectures would be likely
>to
>> do so, I think.
>
>The only compiler I tried this on recently (Sun CC or VC++, I forget
>which) didn't insert padding when the only data member was char[3]. But
>I seem to remember having worked with a C compiler for Intel that
>systematically put all structs on even addresses. But that was a long
>time ago.
Since I posted the original message, I have done some further testing
with my current compiler (Intel C++ 4.0 under win32).
It does not *in general* add redundant padding bytes, but I have found
that in some (obscure) situations where the struct member is a nested
template type then it will then give the containing struct an
alignment of 4 and hence add padding bytes in some cases.
This kind of weirdness is exactly why some kind of standard mandate or
standard #pragma is required; (though in the case of my fixed-size
array class, I have managed to rewrite it to, hopefully, avoid such
vagaries in future).
,Brian Parker
(bparker@uq.net.au)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: bparker@uq.net.au (Brian Parker)
Date: 1999/06/23 Raw View
[Note: this is a (modified) repost- my original reply appears to have
been lost]
On 16 Jun 99 17:12:14 GMT, James.Kanze@dresdner-bank.com wrote:
>...
>The only compiler I tried this on recently (Sun CC or VC++, I forget
>which) didn't insert padding when the only data member was char[3]. But
>I seem to remember having worked with a C compiler for Intel that
>systematically put all structs on even addresses. But that was a long
>time ago.
I have done some experiments with Intel C++ v4.0 for Win32 and it
doesn't add trailing padding in *most* cases, but in some cases where
the single element is a nested template POD type then it capriciously
gives the containing struct an alignment of 4 and hence adds trailing
padding bytes.
In this case, though, I think I can prove that this must be a compiler
bug, because the same padding is not added when the embedded type is
replaced by the equivalent non-templated POD, but these two cases must
be layout-compatible which -> compiler bug. (in any case, alignment
restrictions are supposed to be *implementation-defined*, and I doubt
that the conditions under which this occurred could be precisely
documented.)
Also of interest, the Microsoft documentation on WIN32 structure
alignment (from MSDN) specifies the following struct layout under
WIN32 (this is the WIN32 default behaviour- it can be altered with
#pragmas in the Microsoft compiler) -
"
Type Alignment
char Align on byte boundaries
short (16-bit) Align on even byte boundaries
int and long (32-bit) Align on 32-bit boundaries
float Align on 32-bit boundaries
double Align on 64-bit boundaries
structures Largest alignment requirement of any member
unions Alignment requirement of the first member
"
(I presume that the union case must be a misprint- it also has to be
the largest alignment requirement of any member )
So, because structures have their alignment set to the largest of
their member's alignments (and no larger), there can be no trailing
padding bytes in the one member case
i.e.
struct A {
char [3];
};
sizeof(A) == 3 is guaranteed.
and because struct members are set with an alignment <= their size,
their can be no padding *between* elements of the same type
i.e.
template<typename T>
struct complex {
T re;
T im;
}
sizeof(complex) == sizeof(T)*2;
So it would seem that even though the C++ standard doesn't mandate it,
the ABIs of the major OS's will ensure that compilers provide sane
alignment behaviour- i.e. padding is added *only* to meet hardware
alignment restrictions and is not used as a form of size promotion. I
presume that this would also be the case on the major UNIX platforms.
,Brian Parker
(bparker@uq.net.au)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Lisa Lippincott <lisa_lippincott@advisories.com>
Date: 1999/06/23 Raw View
Regarding a question which I'll paraphrase as
Must the size of "struct{ char c[15]; }" be 15?
Fergus Henderson <fjh@cs.mu.OZ.AU> wrote:
> It's true that the standard allows padding bits in this situation,
> but I don't think they are "likely" -- off-hand, I don't know of any
> implementation which inserts padding bits in that situation, and my guess
> is that only implementations for obscure architectures would be likely to
> do so, I think.
Recent (all?) PowerPC processors have a cache line of 16 bytes; this
makes it a plausible optimization to align such structures on 16-byte
boundaries. Even ignoring the cache, the added padding will allow for
such a structure to be copied more quickly.
--Lisa Lippincott
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/06/23 Raw View
In article <3767A073.3F802A9@wizard.net>,
James Kuyper <kuyper@wizard.net> wrote:
> bparker@uq.net.au wrote:
> ....
> > That said, I really can't see any advantage in allowing an
> > implementation to have an incompatible storage layout for a T and a
> > struct {T} by adding trailing padding bytes- such padding would have
> > to be a gratuitous waste because the alignment of T is presumably
> > optimal for a T and making the alignment of struct{T} more
restrictive
> > could be of no benefit.
>
> In the C9X draft standard, there's an explicit requirement that all
> struct pointers have the same representation and alignment
requirements.
The same representation *and* alignment requirement, or simply the same
representation. Previously, the C/C++ standard has made *no*
requirements on alignment requirements; all mention of alignment
requirements has simply been to give implementations some necessary
freedom, by allowing certain operations to fail. All of the
implementations on modern (byte addressed) machines use the same
representation for *all* pointers; most of the implementations I'm
familiar with do *not* impose the same alignment on all struct's.
--
James Kanze mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orientie objet/
Beratung in objekt orientierter
Datenverarbeitung
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86
27
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <dtribble@technologist.com>
Date: 1999/06/23 Raw View
bparker@uq.net.au wrote:
> struct W {
> T t;
> };
>
> As a practical matter, is anyone aware of a compiler where sizeof(W)
> != sizeof(T) in the example above? I have not encountered such a
> beast on the x86.
No, but I have used a Unix compiler in the past that aligned nested
struct members on fullword boundaries ragardless of their contents:
struct Outer
{
char c;
struct Inner
{
char b;
} s; // Aligned on next fullword
};
I don't recall what system, though.
-- David R. Tribble, dtribble@technologist.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/06/16 Raw View
James Kuyper <kuyper@wizard.net> writes:
>bparker@uq.net.au wrote:
>....
>> That said, I really can't see any advantage in allowing an
>> implementation to have an incompatible storage layout for a T and a
>> struct {T} by adding trailing padding bytes- such padding would have
>> to be a gratuitous waste because the alignment of T is presumably
>> optimal for a T and making the alignment of struct{T} more restrictive
>> could be of no benefit.
>
>In the C9X draft standard, there's an explicit requirement that all
>struct pointers have the same representation and alignment requirements.
>I believe that this is also true, but not explicitly stated, in the
>current C standard.
Yes, as far as I am aware that is correct. But note that the alignment
restrictions that we are talking about here are the restrictions on the
alignment of the pointer, not on what it points to!
>Therefore, since a struct pointer points to it's
>first member, all structs have alignment restrictions at least as strict
>as the most strictly aligned object that any struct can contain.
This conclusion is false.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/06/16 Raw View
In article <7k7l4o$n0r$1@mulga.cs.mu.OZ.AU>,
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote:
> It's true that the standard allows padding bits in this situation,
> but I don't think they are "likely" -- off-hand, I don't know of any
> implementation which inserts padding bits in that situation, and my
guess
> is that only implementations for obscure architectures would be likely
to
> do so, I think.
The only compiler I tried this on recently (Sun CC or VC++, I forget
which) didn't insert padding when the only data member was char[3]. But
I seem to remember having worked with a C compiler for Intel that
systematically put all structs on even addresses. But that was a long
time ago.
--
James Kanze mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orient e objet/
Beratung in objekt orientierter
Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86
27
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: comeau@panix.com (Greg Comeau)
Date: 1999/06/16 Raw View
In article <3766dd89.131611316@news.uq.net.au> bparker@uq.net.au writes:
>I really can't see any advantage in allowing an
>implementation to have an incompatible storage layout for a T and a
>struct {T} by adding trailing padding bytes- such padding would have
>to be a gratuitous waste because the alignment of T is presumably
>optimal for a T and making the alignment of struct{T} more restrictive
>could be of no benefit.
Remember, that in these cases the padding is not a requirement in
the sense that this restriction must exist on all implementations/platforms.
The main reason that the padding at the end is allowed for is because of
arrays. In specific, because of arrays of structs. Consider it T was an
8-bit char on a machine where the natural word use was 16 bits.
Imagine too that you want the compiler to optimize for speed and not
for size. You would hence want the chars oriented in such as way
that padding was used. To apps that need the speed benefit,
then it could be of dire benefit.
>(by contrast, for a struct with multiple members, allowing an
>implementation to choose the amount of padding added between elements
>is useful as it allows an optimisation choice between time or space.)
It's really the same issue. That is to say, consider structobject[1]
to follow structobject[0].
>This is, I think, a significant hole in the C++ object model
This goes back to C BTW.
>that
>limits the utility of small value types- for example, I have written a
>fixed-sized multidimensional array class that is similar to the 2D
>c_array example above, and it would be quite unusable if it did not
>consist of a single memory block, without padding strewn throughout,
>that can be iterated over with a pointer.
Again, this is not a limitation in the true sense, it's up to your
implementation. Suffice it to say that many compiler for many
platforms have switches and #pragma's to allow you to control whether
"packing" takes place or not. As you say above, this is a choice between
time and space. And again, this is so in C. In the following:
// C code
struct xyz {
char c;
} Someobject[99];
there is no guarantee (in C either) that Someobject[1].c is the next
highest immediate byte right after Someobject[0].c. Surprise! :)
>As another example, the c_array class above cannot replace the
>lower-level C array in many cases if there are redundant trailing
>padding bytes e.g.
>
>struct A { // FIRST ONE
> char buf[10];
> int b;
>};
>&
>
>struct A {
> c_array<char, 10> buf;
> int b;
>};
>would, nonintuitively, have incompatible storage layouts.
You can't even generally saying much concrete in terms of the FIRST ONE.
This is why I argue POD and extern "C" and but fighting chances at
compatibility with C, since it's even hard for C compilers running
on the same system to be compatible sometimes.
>Indeed, many value types are simple wrappers of builtin types e.g.
>
>struct fixed_point_4_4 {
> char val;
> // member functions...
>};
>
>and I think that it is an implicit assumption in the design of these
>kinds of classes that a large array of, say, fixed_point_4_4 is
>equivalent to an array of char in space, and if this was not the case
>then- far from being a mere quality-of-implementation issue- it would
>render the class utterly unusable in many situations.
It doesn't need to be the case. This indeed become platform specific
in some case and QoI in others. Yup, size/speed tradeoffs are often
troublesome.
>In short, I think that (in a future revision) the standard can, and
>should, outlaw redundant trailing padding bytes for single element
>structs- specifically,
>for a struct with a single member and which is an aggregate (with the
>exception that constructors are allowed) e.g.
>
>struct W {
> T t;
>};
>
>the ISO C/C++ memory model should guarantee that,
>sizeof(W) == sizeof(T).
>(and alignment of W == alignment of T).
This would be a mistake. See above.
>As a practical matter, is anyone aware of a compiler where sizeof(W)
>!= sizeof(T) in the example above? I have not encountered such a
>beast on the x86.
The x86 favors word operations to be performed on word boundaries.
It does not require this, it just favors it. This then gives you
a distinct choice to make. I haven't looked in a while, but
I would suspect many x86 compiler give you various choices on this
matter.
- Greg
--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C/C++ 4.2.38 -- New Release! We now do Windows too.
Email: comeau@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
*** WEB: http://www.comeaucomputing.com ***
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: bparker@uq.net.au (Brian Parker)
Date: 1999/06/17 Raw View
On 16 Jun 99 17:11:36 GMT, comeau@panix.com (Greg Comeau) wrote:
>...
>Remember, that in these cases the padding is not a requirement in
>the sense that this restriction must exist on all implementations/platforms.
>The main reason that the padding at the end is allowed for is because of
>arrays. In specific, because of arrays of structs. Consider it T was an
>8-bit char on a machine where the natural word use was 16 bits.
>Imagine too that you want the compiler to optimize for speed and not
>for size. You would hence want the chars oriented in such as way
>that padding was used. To apps that need the speed benefit,
>then it could be of dire benefit.
>...
But the point is that guarantees of size can be important for small
user-defined types, and currently there is no standard-conforming way
to create such a user-defined type.
If I wanted to make a size/speed tradeoff in my fixed point class I
would do so explicitly by using, say, an int instead of a smaller type
e.g.
#ifdef OPTIM_SPEED
typedef container_t int
#else
typedef container_t short
#endif
struct fixed_point_8_8 {
container_t data;
// member funcs here
};
and whatever choice I make, I don't want the compiler negating it by
adding unwanted padding.
Imagine if a C/C++ implementation similarly wanted to be "helpful" by
padding out the 16-bit short elements to 32-bits in the interests in
speed in the following array
short a[1000000];
Of course that would be illegal, but the equivalent behaviour with my
16-bit fixed point class is allowed- rendering it effectively
unusable. C++ was designed to allow user-defined types that are as
functional as the built-in types, but currently one can't even define
a class wrapper of a built-in type that is guaranteed interchangeable
with the built-in type itself.
>>(by contrast, for a struct with multiple members, allowing an
>>implementation to choose the amount of padding added between elements
>>is useful as it allows an optimisation choice between time or space.)
>
>It's really the same issue.
There is a difference: ensuring that there is no redundant trailing
padding after single-member structs enables a mechanism for writing
user-defined types of a guaranteed size; in the case of multi-member
structs, implementation-defined alignment padding issues are
inherently unavoidable given the intrinsic alignment restrictions of
the subsequent members.
(side note: the standard talks about types having a
implementation-defined alignments, but in practice compilers give
types different alignments depending on their context i.e.whether they
are allocated directly on the stack or as a member of a struct)
>This is, I think, a significant hole in the C++ object model
>
>This goes back to C BTW.
But it is a much more severe problem in C++ which is designed to
encourage the use of small value types- I agree that it is not much of
a problem in C.
>...
>Again, this is not a limitation in the true sense, it's up to your
>implementation. Suffice it to say that many compiler for many
>platforms have switches and #pragma's to allow you to control whether
>"packing" takes place or not.
In Visual C++ the #pragma pack only changes the amount of padding
*between* member of a struct- it doesn't, AFAIK, *guarantee* that the
struct itself won't be given some large alignment and hence require
trailing padding bytes for a single-member struct.
> As you say above, this is a choice between
>time and space. And again, this is so in C. In the following:
>
> // C code
> struct xyz {
> char c;
> } Someobject[99];
>
>there is no guarantee (in C either) that Someobject[1].c is the next
>highest immediate byte right after Someobject[0].c. Surprise! :)
Agreed, and that's the problem. There can be *no* hardware-imposed
reason for xyz to have an alignment > 1 and hence no need for padding.
Padding out xyz to, say, 32-bits is not strictly due to alignment
requirements- certainly a 32-bit variable may be faster than a char,
but the compiler's automatically making this decision is analogous to
an implementation making, for example, all shorts the same size as
ints because they are faster.
That is, if an implementation pads out xyz to 32 bits, then the
rationale is not that "8 bit objects must be accessed (or are accessed
faster) on 32 boundaries, so let's align xyz to 32 bits", but rather
that "size 32 bit objects are faster than 8 bit objects, so let's make
xyz size 32".
This is a subtle distinction, but the point is that the C++ standard
(sec 9.2/12) only allows padding bytes to be added to meet
*alignment* restrictions (for types without virtual functions and
virtual bases) and hence an implementation cannot merely add trailing
padding bytes to enlarge a struct because larger types are handled
more efficiently. This implies that for-
struct A {
char c;
};
if an implementation does add padding bytes to make A, say, 32 bits
in size then the alignment of A *must* be 4- it can't be given an
alignment of 1.
Sure, in ISO C/C++ an implementation can assign any arbitrary
alignment restriction it likes to any data type, so the above is of
little practical significance, but I mention it merely to emphasize
the *intention* of padding bytes, so that this issue is approached
with the right frame of mind; to restate- padding bytes are used to
ensure alignment restrictions are met, they are not, IMO, intended to
merely enlarge data structures because such enlarged data structures
might be handled more efficiently.
>...
>This is why I argue POD and extern "C" and but fighting chances at
>compatibility with C, since it's even hard for C compilers running
>on the same system to be compatible sometimes.
>
>>Indeed, many value types are simple wrappers of builtin types e.g.
>>
>>struct fixed_point_4_4 {
>> char val;
>> // member functions...
>>};
>>
>>and I think that it is an implicit assumption in the design of these
>>kinds of classes that a large array of, say, fixed_point_4_4 is
>>equivalent to an array of char in space, and if this was not the case
>>then- far from being a mere quality-of-implementation issue- it would
>>render the class utterly unusable in many situations.
>
>It doesn't need to be the case. This indeed become platform specific
>in some case and QoI in others. Yup, size/speed tradeoffs are often
>troublesome.
Sure, all of this can, and currently is, just dismissed as a quality
of implementation issue, but the standard should only give such
implementation freedoms where there are benefits in doing so and no
significant disadvantages.
To paraphrase the essence of my initial proposal in a more general,
and simpler, form-
I believe that the alignment (and hence needed trailing padding bytes)
of a struct should be induced by its members i.e. the alignment of the
containing struct should be guaranteed to be set only to the maximum
alignment of its members. This ensures that a struct meets all of its
alignment requirements- allowing an implementation to give structs
arbitrarily larger alignment restictions (and hence redundant trailing
padding bytes) is *never* required to meet hardware-imposed alignment
requirements.
In the single-member struct case, this formulation reduces to my
original proposal.
Note that to ensure backwards compatibilty with C/C++ implementations
that currently do add redundant trailing padding to structs, the
enforcing of this requirement could be signalled by some form of
standardised #pragma pack.
note:
In the above discussion, when I talk of (hardware-imposed) alignment
restrictions, these can be absolute restrictions (i.e. an addressing
error will occur if they are violated), or relative (i.e. certain
alignments result in faster access for certain built-in types e.g. x86
architecture).
,Brian Parker
(bparker@uq.net.au)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: bparker@uq.net.au
Date: 1999/06/15 Raw View
I have a question concerning the guarantees that the standard makes
with regard to the padding added before and after members in a struct-
specifically I am interested in whether one can be certain that no
padding bytes are added after data in the following class.
// (from CPPPL 3rd ed.)
template <typename T, int sz>
struct c_array {
T data[sz];
};
i.e. if I create a c_array<c_array<int, 2>, 2> will the memory be
contiguous as for an int [2][2]? If not then such a wrapper class is
less useful than it might be.
By my reading of the standard, for T a POD type, c_array is a POD and
so 9.2./17 requires that there be no padding before data, but is an
implementation permitted to give a c_array a larger alignment
requirement than T, such that padding bytes will be needed after data?
Also, if I now add a constructor to c_array it will no longer be a POD
and so even 9.2/17 no longer holds, even though adding a constructor
in no way changes the object layout (unlike adding virtual functions,
base classes or access specifiers); similarly, if T is a non-POD value
type like std::complex then c_array is no longer a POD.
In this respect, 9.2/17 seems overly restrictive- it could perhaps be
made to apply to more general classes ( i.e. "aggregates" +
constructors).
Any comments?
,Brian Parker
(bparker@uq.net.au)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1999/06/15 Raw View
bparker@uq.net.au wrote:
>
> I have a question concerning the guarantees that the standard makes
> with regard to the padding added before and after members in a struct-
> specifically I am interested in whether one can be certain that no
> padding bytes are added after data in the following class.
No. There might be such padding bits. There are likely to be such bits,
if T is a type with less than maximal alignment requirements.
> // (from CPPPL 3rd ed.)
> template <typename T, int sz>
> struct c_array {
> T data[sz];
> };
>
> i.e. if I create a c_array<c_array<int, 2>, 2> will the memory be
> contiguous as for an int [2][2]? If not then such a wrapper class is
There are no contiguity guarantees for that.
> less useful than it might be.
That's right.
> By my reading of the standard, for T a POD type, c_array is a POD and
> so 9.2./17 requires that there be no padding before data, but is an
> implementation permitted to give a c_array a larger alignment
> requirement than T, such that padding bytes will be needed after data?
Yes it is permitted.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/06/15 Raw View
bparker@uq.net.au wrote:
> // (from CPPPL 3rd ed.)
> template <typename T, int sz>
> struct c_array {
> T data[sz];
> };
>
> i.e. if I create a c_array<c_array<int, 2>, 2> will the memory be
> contiguous as for an int [2][2]?
Not necessarily
> If not then such a wrapper class is
> less useful than it might be.
???
--
Valentin Bonnard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: bparker@uq.net.au
Date: 1999/06/16 Raw View
On 15 Jun 99 13:29:02 GMT, James Kuyper <kuyper@wizard.net> wrote:
>bparker@uq.net.au wrote:
>>
>> I have a question concerning the guarantees that the standard makes
>> with regard to the padding added before and after members in a struct-
>> specifically I am interested in whether one can be certain that no
>> padding bytes are added after data in the following class.
>
>No. There might be such padding bits. There are likely to be such bits,
>if T is a type with less than maximal alignment requirements.
>
>> // (from CPPPL 3rd ed.)
>> template <typename T, int sz>
>> struct c_array {
>> T data[sz];
>> };
>>
>> i.e. if I create a c_array<c_array<int, 2>, 2> will the memory be
>> contiguous as for an int [2][2]? If not then such a wrapper class is
>
>There are no contiguity guarantees for that.
>...
Thanks, actually I strongly suspected that this was the case but I was
hoping that, given the equivalence between the first element of a
struct and the element type itself mandated by 9.2/17, that somewhere
the equivalence between a single element struct and the element type
itself would be implied- just wishful thinking on my part.
That said, I really can't see any advantage in allowing an
implementation to have an incompatible storage layout for a T and a
struct {T} by adding trailing padding bytes- such padding would have
to be a gratuitous waste because the alignment of T is presumably
optimal for a T and making the alignment of struct{T} more restrictive
could be of no benefit.
(by contrast, for a struct with multiple members, allowing an
implementation to choose the amount of padding added between elements
is useful as it allows an optimisation choice between time or space.)
This is, I think, a significant hole in the C++ object model that
limits the utility of small value types- for example, I have written a
fixed-sized multidimensional array class that is similar to the 2D
c_array example above, and it would be quite unusable if it did not
consist of a single memory block, without padding strewn throughout,
that can be iterated over with a pointer.
As another example, the c_array class above cannot replace the
lower-level C array in many cases if there are redundant trailing
padding bytes e.g.
struct A {
char buf[10];
int b;
};
&
struct A {
c_array<char, 10> buf;
int b;
};
would, nonintuitively, have incompatible storage layouts.
Indeed, many value types are simple wrappers of builtin types e.g.
struct fixed_point_4_4 {
char val;
// member functions...
};
and I think that it is an implicit assumption in the design of these
kinds of classes that a large array of, say, fixed_point_4_4 is
equivalent to an array of char in space, and if this was not the case
then- far from being a mere quality-of-implementation issue- it would
render the class utterly unusable in many situations.
In short, I think that (in a future revision) the standard can, and
should, outlaw redundant trailing padding bytes for single element
structs- specifically,
for a struct with a single member and which is an aggregate (with the
exception that constructors are allowed) e.g.
struct W {
T t;
};
the ISO C/C++ memory model should guarantee that,
sizeof(W) == sizeof(T).
(and alignment of W == alignment of T).
As a practical matter, is anyone aware of a compiler where sizeof(W)
!= sizeof(T) in the example above? I have not encountered such a
beast on the x86.
,Brian Parker
(bparker@uq.net.au)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/06/16 Raw View
James Kuyper <kuyper@wizard.net> writes:
>bparker@uq.net.au wrote:
>>
>> I have a question concerning the guarantees that the standard makes
>> with regard to the padding added before and after members in a struct-
>> specifically I am interested in whether one can be certain that no
>> padding bytes are added after data in the following class.
>
>No. There might be such padding bits. There are likely to be such bits,
>if T is a type with less than maximal alignment requirements.
It's true that the standard allows padding bits in this situation,
but I don't think they are "likely" -- off-hand, I don't know of any
implementation which inserts padding bits in that situation, and my guess
is that only implementations for obscure architectures would be likely to
do so, I think.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1999/06/16 Raw View
bparker@uq.net.au wrote:
....
> That said, I really can't see any advantage in allowing an
> implementation to have an incompatible storage layout for a T and a
> struct {T} by adding trailing padding bytes- such padding would have
> to be a gratuitous waste because the alignment of T is presumably
> optimal for a T and making the alignment of struct{T} more restrictive
> could be of no benefit.
In the C9X draft standard, there's an explicit requirement that all
struct pointers have the same representation and alignment requirements.
I believe that this is also true, but not explicitly stated, in the
current C standard. Therefore, since a struct pointer points to it's
first member, all structs have alignment restrictions at least as strict
as the most strictly aligned object that any struct can contain. This
representation and alignment requirement is needed, in order to allow
pointers to incomplete classes to be passed around.
I believe that the same is true in C++, but I've looked for and haven't
found corresponding wording in the C++ standard.
....
> struct W {
> T t;
> };
>
> the ISO C/C++ memory model should guarantee that,
> sizeof(W) == sizeof(T).
> (and alignment of W == alignment of T).
>
> As a practical matter, is anyone aware of a compiler where sizeof(W)
> != sizeof(T) in the example above? I have not encountered such a
> beast on the x86.
Have you tried T='char'? The x86 has less severe alignment restrictions
than many other machines, but even it prefers even alignement over odd
alignment.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]