Alignment of X vs char[sizeof (X)] field

  • Follow


Hi,

Provided I have:

typename Y; // any type; known at this point

class X
{
char array[sizeof (Y)];
};

Is it safe to assume that I can always construct an Y on the top of 'array', i.e.

new (array) Y (whatever);

Thanks,
Radoslav Getov

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply rgetov643 (2) 12/21/2003 4:40:03 PM

In message <1e27bd36.0312210437.1c70858@posting.google.com>, Radoslav 
Getov <rgetov@ultraheap.com> writes
>Provided I have:
>
>typename Y; // any type; known at this point

This is not a supported declarative statement in Standard C++. You can 
have:

class Y;
struct Y;
union Y;

but other declarations of typenames are not supported.
>
>class X
>{
>char array[sizeof (Y)];

Exactly how would you expect a compiler to know the sizeof an incomplete 
type? Compilers are not allowed to either read the future or the 
programmers mind.

>};
>
>Is it safe to assume that I can always construct an Y on the top of 'array', i.e.
Have you found a compiler that will even pretend to understand your 
code? Because until you do your question is vacuous.

>
>new (array) Y (whatever);

I assume you are intending to use a placement new but in addition to all 
the other problems your code will be vulnerable to alignment issues.

Perhaps you could share with us what it is you want to achieve rather 
than asking about an imagined solution.


-- 
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
                             or http://www.robinton.demon.co.uk


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Francis 12/21/2003 8:43:52 PM


"Radoslav Getov" <rgetov@ultraheap.com> wrote in message news:1e27bd36.0312210437.1c70858@posting.google.com...

> 
> Is it safe to assume that I can always construct an Y on the top of 'array', i.e.
> 
> new (array) Y (whatever);
> 
No, char arrays are not necessarily aligned to anything.  

However the value of "new char[sizeof(Y)]" is guaranteed to be
"super"-aligned (i.e. suitable for any object).


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ron 12/21/2003 8:47:03 PM


Radoslav Getov schrieb:

> Hi,
>
> Provided I have:
>
> typename Y; // any type; known at this point
>
> class X
> {
> char array[sizeof (Y)];
> };
>
> Is it safe to assume that I can always construct an Y on the top of 'array', i.e.
>
> new (array) Y (whatever);

No, because of alignment issues. For example, class Y might have other alignment
requirements than an array of chars.


cheers,

Thomas

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Thomas 12/21/2003 8:47:31 PM

"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message news:awR3ayFFed5$EwcL@robinton.demon.co.uk...
> In message <1e27bd36.0312210437.1c70858@posting.google.com>, Radoslav 
> Getov <rgetov@ultraheap.com> writes
> >Provided I have:
> >
> >typename Y; // any type; known at this point
> 
> This is not a supported declarative statement in Standard C++. You can 
> have:
I don't think he literally meant "typename".    He just meant that Y
was specifically declared with a fully defined type.

SomeType Y;

probably would have been better to avoid confusion with the language
keyword.


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ron 12/22/2003 1:17:49 AM

On 21 Dec 2003 11:40:03 -0500, rgetov@ultraheap.com (Radoslav Getov)
wrote:

>Hi,
>
>Provided I have:
>
>typename Y; // any type; known at this point
>
>class X
>{

static std::size_t const Yalignment = ::boost::alignment_of<Y>::value;
typedef ::boost::type_with_alignment<Yalignment>::type Yaligner_t;
static int const test_array_size = sizeof(Y) / sizeof(Yaligner_t);
static int const array_size = sizeof(Y) % sizeof(Yaligner_t)? 
  test_array_size + 1? test_array_size;

aligner_t array[array_size];

>};
>
>Is it safe to assume that I can always construct an Y on the top of 'array', i.e.
>
>new (array) Y (whatever);

No, you need to ensure correct alignment (char has an alignment of 1,
Y may not). The above (using Boost type_traits) attempts to do that.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply tom_usenet 12/22/2003 12:24:00 PM

Francis Glassborow wrote:
> This is not a supported declarative statement in Standard C++. You can 
> have:
> 
> class Y;
> struct Y;
> union Y;
> 
> but other declarations of typenames are not supported.

Can you tell me why? Especially I see no reason to exclude 'enum' from
above list(I know for example that MSVC6 accepts it as extension). Another
nice addition would be to have the OP's 'typename' to just declare a type
without telling more precisely what it is, like it is possible with
template parameters.

thanks

Uli

-- 
Questions ?
see  C++-FAQ Lite: http://parashift.com/c++-faq-lite/  first !


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ulrich 12/22/2003 12:25:10 PM

In message <bs6d39$9tgp9$1@ID-178288.news.uni-berlin.de>, Ulrich 
Eckhardt <doomster@knuut.de> writes
>Francis Glassborow wrote:
>> This is not a supported declarative statement in Standard C++. You can
>> have:
>>
>> class Y;
>> struct Y;
>> union Y;
>>
>> but other declarations of typenames are not supported.
>
>Can you tell me why? Especially I see no reason to exclude 'enum' from
>above list(I know for example that MSVC6 accepts it as extension). Another
>nice addition would be to have the OP's 'typename' to just declare a type
>without telling more precisely what it is, like it is possible with
>template parameters.

The above three are required to have certain common properties, in 
particular they are required to have same size and laid out pointers so 
that just knowing that Y is a name for a class, struct or union ensures 
that Y* is fully defined (and so is Y&). However that requirement does 
not apply to other types, nor should it.

We have had interminable debates about (forward) declaring enums but 
allowing such would place additional requirements on the underlying type 
of an enum, ones that we do not want to provide as they would mean 
fatter code on many systems.


-- 
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
                             or http://www.robinton.demon.co.uk


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Francis 12/22/2003 2:12:56 PM

"Ron Natalie" <ron@sensor.com> wrote in message news:<3fe60f93$0$70025$9a6e19ea@news.newshosting.com>...

> I don't think he literally meant "typename".    He just meant that Y
> was specifically declared with a fully defined type.
> 
> SomeType Y;
> 
> probably would have been better to avoid confusion with the language
> keyword.

Thanks for the clarification - I'll try to be more clear next time.

The question was about alignment indeed: I know that new char [sizeof
(X)] is suitably aligned for any X, and I hoped the same was true for
a field array. Anyway, it seems the answer is 'no'.

Does anybody know how to force the alignment of (say char array field)
without actually declaring an X field? (I am trying to use 'placement
new' over a static field, without need to dynamically allocate
memory).

Radoslav Getov

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply rgetov 12/22/2003 2:14:15 PM

"Ulrich Eckhardt" <doomster@knuut.de> wrote in message news:bs6d39$9tgp9$1@ID-178288.news.uni-berlin.de...
> Francis Glassborow wrote:
> > This is not a supported declarative statement in Standard C++. You can 
> > have:
> > 
> > class Y;
> > struct Y;
> > union Y;
> > 
> > but other declarations of typenames are not supported.
> 
> Can you tell me why? Especially I see no reason to exclude 'enum' from
> above list

Because all enums need not be the same size and you can't determine what
size the enum is unless you know what the enumerators are.


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Ron 12/22/2003 7:18:20 PM

* Radoslav Getov <rgetov@ultraheap.com>:
 > Does anybody know how to force the alignment of (say char array field)
 > without actually declaring an X field?

Not sure how to do this, but as an alternative solution you could
do the alignment inside your implementation.  If you know your target
platforms and their alignment requirements, this shouldn't be too hard.
For example, you could align whatever object you are going to place into
the array on a 16 byte boundary (just make sure your array is big enough
to accomidate the worse case 16 byte alignment).

Or, maybe you could declare what you know is the largest built-in type
for your target architecture as the first parameter before your char
array:

typedef long double align_t;   // strictest alignment requirements

class x {
    align_t align;       // used for alignment
    char    array[128];

// ....

};

Not sure about this approach...maybe the experts on the newsgroup can
tear this one up.... ;)








      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Dirt 12/23/2003 10:56:06 AM

rgetov@ultraheap.com (Radoslav Getov) wrote in message
news:<1e27bd36.0312220516.34febe7b@posting.google.com>...
 > "Ron Natalie" <ron@sensor.com> wrote in message
 > news:<3fe60f93$0$70025$9a6e19ea@news.newshosting.com>...

 > > I don't think he literally meant "typename".  He just meant that Y
 > > was specifically declared with a fully defined type.

 > > SomeType Y;

 > > probably would have been better to avoid confusion with the language
 > > keyword.

 > Thanks for the clarification - I'll try to be more clear next time.

 > The question was about alignment indeed: I know that new char [sizeof
 > (X)] is suitably aligned for any X, and I hoped the same was true for
 > a field array. Anyway, it seems the answer is 'no'.

 > Does anybody know how to force the alignment of (say char array field)
 > without actually declaring an X field? (I am trying to use 'placement
 > new' over a static field, without need to dynamically allocate
 > memory).

In theory, you can't.  In practice, using a union with double is usually
sufficient; I have a union MaxAlign with just about all built-in types
for this:

     union
     {
         unsigned char       data[ N ] ;
         MaxAlign            dummyForAlignment ;
     } ;

The standard doesn't exclude the possibility that something in the type
I construct causes even stricter alignment, but in practice, no
implementation will use stricter alignment than necessary, and the
maximum alignment constraints are set by a certain number of built-in
types -- typically, double is the worse (although long double might also
be a candidate -- theoretically, long and pointers too, although I don't
know of any pratical example).

If not, certain compilers have extensions to force alignment.

--
James Kanze           GABI Software        mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/     http://www.gabi-soft.fr
                     Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply kanze 12/23/2003 11:21:35 AM

"Ron Natalie" <ron@sensor.com> wrote in message
news:<3fe6b2ec$0$468$9a6e19ea@news.newshosting.com>...
 > "Ulrich Eckhardt" <doomster@knuut.de> wrote in message
 > news:bs6d39$9tgp9$1@ID-178288.news.uni-berlin.de...
 > > Francis Glassborow wrote:
 > > > This is not a supported declarative statement in Standard C++. You
 > > > can have:

 > > > class Y;
 > > > struct Y;
 > > > union Y;

 > > > but other declarations of typenames are not supported.

 > > Can you tell me why? Especially I see no reason to exclude 'enum' from
 > > above list

 > Because all enums need not be the same size and you can't determine
 > what size the enum is unless you know what the enumerators are.

That's also true for classes and unions -- classes can vary enormously
in size.  I think you mean that the pointers can be different sizes.  In
theory, this is true, but I think that to be a valid argument, you'd
have to point to at least one implementation where this is actually the
case.

I suspect that the real reason is simply that no one ever felt it
necessary.  I still don't see where there is any real need.

--
James Kanze           GABI Software        mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/     http://www.gabi-soft.fr
                     Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply kanze 12/23/2003 11:23:00 AM

Francis Glassborow <francis.glassborow@robinton.demon.co.uk> wrote in
message news:<9SueiRA4hu5$EwLT@robinton.demon.co.uk>...
 > In message <bs6d39$9tgp9$1@ID-178288.news.uni-berlin.de>, Ulrich
 > Eckhardt <doomster@knuut.de> writes
 > >Francis Glassborow wrote:
 > >> This is not a supported declarative statement in Standard C++. You
 > >> can have:

 > >> class Y;
 > >> struct Y;
 > >> union Y;

 > >> but other declarations of typenames are not supported.

 > >Can you tell me why? Especially I see no reason to exclude 'enum'
 > >from above list(I know for example that MSVC6 accepts it as
 > >extension). Another nice addition would be to have the OP's
 > >'typename' to just declare a type without telling more precisely what
 > >it is, like it is possible with template parameters.

 > The above three are required to have certain common properties, in
 > particular they are required to have same size and laid out pointers
 > so that just knowing that Y is a name for a class, struct or union
 > ensures that Y* is fully defined (and so is Y&). However that
 > requirement does not apply to other types, nor should it.

 > We have had interminable debates about (forward) declaring enums but
 > allowing such would place additional requirements on the underlying
 > type of an enum, ones that we do not want to provide as they would
 > mean fatter code on many systems.

On many systems?  Could you name a few?

About the only one I can think of which is still in production where
this might be the case is the Unisys mainframes.  And I would stress the
"might": if pointers have different sizes, the machine is word
addressed, accessing individual char's is less efficient, and it is
probable that the implementation would always make an enum at least the
size of an int (and so addressable with the smaller sized pointer).

Personally, I don't see any real necessity for supporting this -- if the
enum is visible at the interface level, client code probably needs the
constants anyway, so you don't gain anything.  (There are a few
exceptions, but as far as I'm concerned, they aren't frequent enough to
be worth bothering with.)  But if someone feels that allowing it would
actually help with something, and wants to go to the bother to make a
proposition, anyone trying to use the above reason against it had better
be ready to come up with some concrete examples -- existing compilers
where the size of a pointer to an enum varies.

--
James Kanze           GABI Software        mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/     http://www.gabi-soft.fr
                     Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply kanze 12/23/2003 11:23:21 AM

In message <d6652001.0312230054.5cac66f9@posting.google.com>, 
kanze@gabi-soft.fr writes
>I suspect that the real reason is simply that no one ever felt it
>necessary.  I still don't see where there is any real need.

Those responsible (and I was present and part of that group) for the 
enum specification (which is less restrictive than C's) wanted to allow 
compiler's maximum opportunity for optimising the space requirement. 
That meant that we chose to allow an enum to use an underlying 
signed/unsigned char. We also permitted an enum to use, but only if 
necessary, an integer type larger than int. The cost of allowing these 
things was to sacrifice any requirements on pointer size or layout.

There were more radical things we could have done such as requiring that 
an enum pointer always had a specific size and layout however the costs 
of such specification did not seem to have commensurate benefits.

While there were (and still are) very real benefits as well as needs 
(mutual references) for (forward) declaration of classes, structs, and 
(because they come under the same rules) unions. The benefits of 
supporting the same for enums did not seem to us to be worth the cost. 
Personally I think that continues to be true today.

-- 
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
                             or http://www.robinton.demon.co.uk


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Francis 12/23/2003 5:08:04 PM

Francis Glassborow <junkx@robinton.demon.co.uk> writes:

| In message <d6652001.0312230054.5cac66f9@posting.google.com>, 
| kanze@gabi-soft.fr writes
| >I suspect that the real reason is simply that no one ever felt it
| >necessary.  I still don't see where there is any real need.
| 
| Those responsible (and I was present and part of that group) for the 
| enum specification (which is less restrictive than C's) wanted to allow 
| compiler's maximum opportunity for optimising the space requirement. 

And real programs to take advantage of that.  I just came across sevral
manuals for embeddeds system that recommend GCC's -fshort-enum (that
strictly implement that idea of possible optimisations). 

-- 
                                                       Gabriel Dos Reis 
                                           gdr@integrable-solutions.net

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Gabriel 12/24/2003 2:09:59 AM

 > Francis Glassborow <francis.glassborow@robinton.demon.co.uk> wrote
 >  > We have had interminable debates about (forward) declaring enums but
 >  > allowing such would place additional requirements on the underlying
 >  > type of an enum, ones that we do not want to provide as they would
 >  > mean fatter code on many systems.

kanze@gabi-soft.fr wrote
 > On many systems?  Could you name a few?
 >
 > About the only one I can think of which is still in production where
 > this might be the case is the Unisys mainframes.

If there are two Unisys mainframes in the world, this could count as
"many systems" (dictionary.com says that "many" means "large
indefinite number", but it could also mean "more than one", as in a
"one-to-many" relationship in a database).

:-)

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply allan_w 12/27/2003 11:06:57 AM

16 Replies
97 Views

(page loaded in 0.153 seconds)


Reply: