Topic: packed" objects


Author: rfg@NCD.COM (Ron Guilmette)
Date: 24 Aug 90 05:36:18 GMT
Raw View
In article <56735@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>In article <1227@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>|
>|The problem of packing across inheritance boundaries is a different
>|matter however...
>
>Okay, sounds interesting.  How about a proposal about how this should
>work?  I'd like to propose that your suggestion should still allow
>portability across machines with differing packing strategies, and should
>not be onerous to people who aren't interested in these details....

I could have sworn that I already *did* make a proposal.  How about:

 class base { int i; };
 class derived : public packed base { int j; };

I'm assuming that the programmer might wish to specify exactly *which*
base class is supposed to get packed up against the fields of the derived
class.

Of course the example given above will never fly (politically) because it
introduces a new keyword.  (God forbid :-)  Of course you could always get
around that problem in the standard C++ way, i.e. by reusing yet another
existing keyword which should not be reused and by assigning it some new
and different meaning in one particular syntactic location.  So how about:

 class base { int i; };
 class derived : public auto base { int j; };

It reads poorly, and it the meaning has nothing whatsoever to do with
auto'ness, but hey!  It creates no new keywords! :-)

--

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.




Author: rfg@NCD.COM (Ron Guilmette)
Date: 18 Aug 90 06:57:44 GMT
Raw View
In article <56637@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>In article <1030@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>
>>>* Require current field ordering restrictions be maintained on things declared
>>>"struct", but removed restrictions on anything declared "class."
>>
>>Bad idea.
>
>I don't disagree, but state why you don't like this one so the rest of
>us can follow your logic.

As I have stated, I am adamantly opposed to anything which allows a C++
compiler to mess with the layout of *any* of *my* data structures (whether
they be structs or classes or unions) unless of course such a `feature'
(and I use the term loosely) were provided as a kind of upward compatible
extension via #pragma's or special compiler options.  In other words,
I would prefer it if all compilers were required to accept (as the primary
default) the assumption that I know what I'm doing when I specify an
ordering for my fields.

Believe it or not, in practice I find that I *do* know what I'm doing
when I write a struct type definition (and likewise a class type definition).
As a matter of fact, I often spend a good deal of time thinking about how
to do such things so that I get "efficient space usage".

I certainly know what I'm doing (better than *any* compiler ever will) when
I'm specifying data structures that *must* be layed out a certain way (e.g.
because they reflect a memory mapped device's layout or because the layout
is otherwise dictated by external constraints such as existing formats in
disk files or over communications media).

Just because some people feel that some mythical future compiler will be able
to layout data structures better than they themselves can, this is no reason
to penalize the rest of us (and provide us with *no* recourse) when we want
or need to have precise control of the layout of our data structures.

>The problem is, the proposal intends not only to address the issue of
>"packing up against" a base class, but also the possibility of
>"packing into" a base class...

I consider these to be two different problems.  Packing fields within a
struct (or class) is something I can do perfectly well right now with
C, thank you.  If C++ would just stick to its roots in this respect I
would have all of the control that I need to take care of packing the
fields within a struct (or class) myself.

The problem of packing across inheritance boundaries is a different
matter however.  This is an entirely new problem in C++, and (I feel)
it needs to have a proper solution so that the programmer can (once
again) be in complete control over data structure layout.  (Right now,
he's not because the current de-facto standard doesn't mandate anything
in particular about the packing, or lack thereof, which occurs at these
boundaries.)
--

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 20 Aug 90 17:21:18 GMT
Raw View
In article <1227@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
|I consider these to be two different problems.  Packing fields within a
|struct (or class) is something I can do perfectly well right now with
|C, thank you.  If C++ would just stick to its roots in this respect I
|would have all of the control that I need to take care of packing the
|fields within a struct (or class) myself.
|
|The problem of packing across inheritance boundaries is a different
|matter however.  This is an entirely new problem in C++, and (I feel)
|it needs to have a proper solution so that the programmer can (once
|again) be in complete control over data structure layout.  (Right now,
|he's not because the current de-facto standard doesn't mandate anything
|in particular about the packing, or lack thereof, which occurs at these
|boundaries.)

Okay, sounds interesting.  How about a proposal about how this should
work?  I'd like to propose that your suggestion should still allow
portability across machines with differing packing strategies, and should
not be onerous to people who aren't interested in these details....




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 16 Aug 90 18:53:53 GMT
Raw View
In article <1030@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>In article <56165@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>>Use 'extern "C"' where an object needs backwards
>>compatibility to "C" packing order.
>
>Huh?

Just what it says.  Using 'extern "C"' around a class or structure
definition will give you a structure that is compatible with your
C compiler [from the same vendor 1/2 :-]  Using 'extern "Pascal"' around
a class or structure definition will give you a structure that is
compatible with your Pascal compiler [from the same vendor 1/4 :-]
Otherwise, you'd not be gauranteed any backwards compatability between
the layout of a C++ class/structure, and a C or Pascal structure.

>>* Require current field ordering restrictions be maintained on things declared
>>"struct", but removed restrictions on anything declared "class."
>
>Bad idea.

I don't disagree, but state why you don't like this one so the rest of
us can follow your logic.

>>* Introduce an explicit keyword "packed" or similar.  Declaring a base class
>>"packed" turns off field ordering restrictions in that class and its
>>derivatives, as well as representing a directive to the compiler that small
>>size is to be preferred to fast access.  Possibly vtable ptrs could also
>>be replaced with smaller type tags in such classes....
>
>Since the issue involves the boundary between a derived class and exactly
>one of its base classes, I suggest that perhaps "packed" should be a way
>of doing inheritance, e.g.:
>
> class doe : public rea, packed public me { ... };
>
>would specify that the earliest field of `doe' should get packed up against
>the latest field of `me'.

The problem is, the proposal intends not only to address the issue of
"packing up against" a base class, but also the possibility of
"packing into" a base class.  Since "packing into" a base class might
require an explicit awareness in the base class not to mess with
unused fields, the packed'ness needs to be declared in the base class.
Two choices then might be to make packed'ness a inherited attribute,
or to have to be redeclared in subsequent derived classes.  Seems to me
once a superclass has a packed attribute, the die has been cast,
any backwards compatibility is lost, and subsequent derived classes
should automatically follow their base class's packed or unpacked'ness.
Likewise, in MI having one base class packed would be enough to make
derived classes "packed."  "Packed" in this sense just means that C
packing rules are not necessarily being followed.




Author: jbuck@galileo.berkeley.edu (Joe Buck)
Date: 2 Aug 90 18:44:28 GMT
Raw View
In article <1990Aug2.142410.10541@watmath.waterloo.edu>,
gjditchfield@watmsg.uwaterloo.ca (Glen Ditchfield) writes:
|> Reordering does not have to go so far as to change the offsets of inherited
|> members.  The rule could be that new members can be placed in holes left by
|> padding in the superclass or in unused portions of storage units that
|> contain inherited bitfields.  I think this would do all the packing that
|> Jim Adcock originally wanted, without affecting current implementations of
|> inheritance.

Consider this example:

class Base {
 char c;
 int i;
}

Let's say there's a hole between c and i.

class Derived : public Base {
 char c2;
}

I take it you want to insert the c2 in the hole.

But does this mean that all methods of class Base have to make sure to preserve
the contents of holes, under all conditions, because the Base object may really
be a Derived object?  In this case that wouldn't be too hard, but what if c and
c2 were bitfields instead?  Think about compiler-generated assignment
operators.
Seems to me they'd get more complex.


--
Joe Buck
jbuck@galileo.berkeley.edu  {uunet,ucbvax}!galileo.berkeley.edu!jbuck




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 2 Aug 90 20:27:19 GMT
Raw View
In article <56165@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>Proposed:
>
>We need a way to "pack" objects over inheritence boundaries, and possibly
>between labeled fields of a declaration.  I do not propose here exactly
>what the "right" way to do this is.

I should clarify that I was not proposing that every compiler actually has
to do the packing, nor that there need to be a standard way to do that
packing.  What I was proposing is that we need a way to turn off the standard
C++ field ordering restrictions, such that a compiler can choose to lay out
those fields in any order it feels is appropriate.  Perhaps the easiest way
to accomplish this is just throw away the traditional restrictions on field
ordering.




Author: hopper@ux.acs.umn.edu (hopper)
Date: 2 Aug 90 23:23:53 GMT
Raw View
In article <1990Aug1.171148.22119@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>> B) Certain C++ languages (Lattice C++ for the Amiga for one) make
>> extensive use of C++ structures/classes to hide the cruft of working
>> with the system libraries.  Surely a desireable end.  However, the
>> system libraries depend on a specific order of elements within a
>> structure and would likely break under either of the above.
>
>This just means that there have to be enough guarantees on behavior that
>the library code can assume a stable base.  This is much the same as what
>would be needed to make inheritance work anyway, so I don't see a problem
>there in general.

 One of the nicer things in C, (and C++) is to be able to create
machine specific data sructures that correspond to some area in memory.
(i.e. bit-fields and such). I agree that writing machine specific code is
generally undesirable, sometimes it is necessary.

 Currently the methods of structure member ordering, and packing
specifications are easy enough to figure out that you can easily write a
structure that models some hardware/OS data structure rather well. If
packing of bit-fields, and structure members became a standard, unavoidable
thing, this would no longer be easy to do. In other words, you would no
longer be able to write an OS in C++.

Have fun,
UUCP: rutgers!umn-cs!ux.acs.umn.edu!hopper   (Eric Hopper)
     __                    /)                       /**********************/
    / ')                  //                         * I went insane to   *
   /  / ______  ____  o  //  __.  __  o ____. . _    * preserve my sanity *
  (__/ / / / <_/ / <_<__//__(_/|_/ (_<_(_) (_/_/_)_  * for later.         *
Internet:              />                            * -- Ford Prefect    *
hopper@ux.acs.umn.edu </  #include <disclaimer.h>   /**********************/




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 3 Aug 90 18:55:37 GMT
Raw View
In article <6785@netxcom.DHL.COM> ewiles@netxcom.DHL.COM (Edwin Wiles) writes:
>In article <56165@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>>* Throw out the current C++ restrictions on field ordering entirely.  What
>>does it buy us anyway?  Use 'extern "C"' where an object needs backwards
>>compatibility to "C" packing order.
>>* Require current field ordering restrictions be maintained on things declared
>>"struct", but removed restrictions on anything declared "class."
>
>Let's see if I understand what you're proposing in the above two options.
>
>I get the idea that what you want is to have the compiler be able to
>assemble the fields in the classes in any order, rather than strictly
>in the order in which they were defined.  Which *would* allow you to
>pack bit fields together in the way you want, however....

Compilers already do not have to assemble the fields in the order they are
defined.  The basic present restriction is that within a labeled region
[labeled by private: public: protected:] fields are to be placed at increasing
addresses.  The order in which various labeled regions are placed is compiler
dependent.  The spacing between those fields is compiler dependent -- one
compiler might pack shorts on 2-byte boundaries, another might pack shorts
on 4-byte boundaries -- representing two different compiler's choices of
how they feel the tradeoff between speed and space should be handled.
Also, where hidden fields [vtable pointers, virtual base pointers] are
packed is also compiler dependent.

Other issues in getting C++ compilers to be compatible are name mangling
conventions, global ::new conventions, vtable agreements, calling conventions,
optimization conventions,....

...So I believe C++ compiler compatibility is outside the scope of the language.
If a group of compilers are going to be compatible, their people are going
to have to form some kind of consortium, and agree on hundreds of little
nagging details.

>I would argue against both of the above as a 'default' for the following
>reasons:
>
> A) You would not be guaranteed that a data file written by a given
> program on one machine, would be readable by the same program compiled
> on a different machine under a different implementation of C++.
> (Assuming that hardware and byte ordering are the same, the order
> of structure/class elements wouldn't necessarily be the same.)

This will not work today anyway -- for the reasons listed above.

> B) Certain C++ languages (Lattice C++ for the Amiga for one) make
> extensive use of C++ structures/classes to hide the cruft of working
> with the system libraries.  Surely a desireable end.  However, the
> system libraries depend on a specific order of elements within a
> structure and would likely break under either of the above.

Yes, I agree there is a need to have a way to maintain backwards compatibility
with prior "C" libraries -- and their associated data structures.  This is
easily accomplished if a C++ compiler honors the 'extern "C"' to mean
that C naming conventions are to be used, that C calling conventions are
to be used, and that C packing conventions are to be used.  Likewise
'extern "Pascal"' can be used where Pascal naming conventions are to be
used, Pascal calling conventions, and Pascal packing conventions.

>>* Introduce an explicit keyword "packed" or similar.  Declaring a base class
>>"packed" turns off field ordering restrictions in that class and its
>>derivatives, as well as representing a directive to the compiler that small
>>size is to be preferred to fast access.  Possibly vtable ptrs could also
>>be replaced with smaller type tags in such classes....
>
>This would be more acceptable, as it leaves it as an option that the programmer
>can use if appropriate, but doesn't force the issue.  However, it could still
>have the problems shown above, and should therefore NOT be used where
>portability is important.  If the structure/class is purely internal, never
>appearing outside of the program in question, then it's acceptable.

This is an argument relative to maintaining historical standards verses
introducing innovative new techniques.  Compilers can choose to be innovative,
or they can choose to be conservative and maintain old packing standards.
The marketplace can decide what compiler they like best.  Or these choices
can be handled via options.  Likewise, many C++ compilers do not follow
"C" calling conventions, but rather use Pascal calling conventions, or register
passing conventions.  The language does not dictate that C calling conventions
continue to be used. Why should the language dictate even the minimal amount
of packing order restrictions presently in place?  What legal things can a
programmer do to make use of the present packing order restrictions?  Present
packing order restrictions do almost nothing towards helping to C++ compilers
be compatible.  Nor do they help programmers.  Lets get rid of the packing
order restrictions.




Author: hopper@ux.acs.umn.edu (hopper)
Date: 3 Aug 90 23:11:37 GMT
Raw View
In article <MCGRATH.90Aug3011039@paris.Berkeley.EDU> mcgrath@paris.Berkeley.EDU (Roland McGrath) writes:
>In article <1944@ux.acs.umn.edu> hopper@ux.acs.umn.edu (hopper) writes:
>    One of the nicer things in C, (and C++) is to be able to create
>   machine specific data sructures that correspond to some area in memory.
>   (i.e. bit-fields and such). I agree that writing machine specific code is
>   generally undesirable, sometimes it is necessary.
                     .
                     .
                     .
>   thing, this would no longer be easy to do. In other words, you would no
>   longer be able to write an OS in C++.
>
>We are talking here about Standard C++.  In Standard C, you can't necessarily
>have a `struct' that corresponds to a hardware layout, because there may be
>padding (and the standard leaves it completely up to the implementation, except
>that there can be no padding before the first member).
>
>If you want to have a `struct' that corresponds to some hardware thing or
>whatever, and you know enough about the C compiler's padding conventions to do
>this, then write it inside `extern "C"' in C++.  This still doesn't guarantee
>you a damn thing as far as the standards are concerned.
>
>"We can't allow A in the standard because it makes it more difficult to do
>nonstandard, unportable hack B (which is not guaranteed by the standard to
>work, but which probably will most days of the week)" does not sound to me like
>a reasonable argument.

 I think you've missed my point. One of the nicer things about C, and
C++ is the ability to write anything you darn well please, whether it
accesses memory mapped I/O directly, models a complicated hardware
structure, or what have you. If you suddenly make the ordering of you
structures & classes hard to figure out, such things will no longer be very
easy.

 I like the idea of a compiler being able to re-order my data
structures to make them more efficient, but having it do this all the time
could get to be VERY annoying if I'm trying to do something with the things
mentioned above. I want C++ to remain a language that one can write an OS
in.

Have fun,
UUCP: rutgers!umn-cs!ux.acs.umn.edu!hopper   (Eric Hopper)
     __                    /)                       /**********************/
    / ')                  //                         * I went insane to   *
   /  / ______  ____  o  //  __.  __  o ____. . _    * preserve my sanity *
  (__/ / / / <_/ / <_<__//__(_/|_/ (_<_(_) (_/_/_)_  * for later.         *
Internet:              />                            * -- Ford Prefect    *
hopper@ux.acs.umn.edu </  #include <disclaimer.h>   /**********************/




Author: mcgrath@paris.Berkeley.EDU (Roland McGrath)
Date: 3 Aug 90 08:10:39 GMT
Raw View
In article <1944@ux.acs.umn.edu> hopper@ux.acs.umn.edu (hopper) writes:
    One of the nicer things in C, (and C++) is to be able to create
   machine specific data sructures that correspond to some area in memory.
   (i.e. bit-fields and such). I agree that writing machine specific code is
   generally undesirable, sometimes it is necessary.

    Currently the methods of structure member ordering, and packing
   specifications are easy enough to figure out that you can easily write a
   structure that models some hardware/OS data structure rather well. If
   packing of bit-fields, and structure members became a standard, unavoidable
   thing, this would no longer be easy to do. In other words, you would no
   longer be able to write an OS in C++.

We are talking here about Standard C++.  In Standard C, you can't necessarily
have a `struct' that corresponds to a hardware layout, because there may be
padding (and the standard leaves it completely up to the implementation, except
that there can be no padding before the first member).

If you want to have a `struct' that corresponds to some hardware thing or
whatever, and you know enough about the C compiler's padding conventions to do
this, then write it inside `extern "C"' in C++.  This still doesn't guarantee
you a damn thing as far as the standards are concerned.

"We can't allow A in the standard because it makes it more difficult to do
nonstandard, unportable hack B (which is not guaranteed by the standard to
work, but which probably will most days of the week)" does not sound to me like
a reasonable argument.

You must remember that we are talking about the standard for C++.  I propose
simply that the standard make no restrictions about structure member order
(outside of `extern "C"', since inside `extern "C"' the restrictions of
standard C apply).  That member reordering makes various implementation details
difficult (like that base classes must deal with derived classes' members
possibly being in between the base class's members) is none of the standard's
bloody business.  It's an implementation problem.  If all these problems are as
insurmountable as you seem to think, then no implementor will overcome them,
and no implementation will reorder structure members.  I don't know how to
implement reordering correctly either, but I'm more than willing to concede
that some C++ implementor out there is more clever than I, and see no reason to
prohibit someone else from doing something I can't figure out how to do.
--
 Roland McGrath
 Free Software Foundation, Inc.
roland@ai.mit.edu, uunet!ai.mit.edu!roland




Author: rpk@wheaties.ai.mit.edu (Robert Krajewski)
Date: 5 Aug 90 21:07:44 GMT
Raw View
In article <1944@ux.acs.umn.edu> hopper@ux.acs.umn.edu (Eric Hopper) writes:
> Currently the methods of structure member ordering, and packing
>specifications are easy enough to figure out that you can easily write a
>structure that models some hardware/OS data structure rather well.

Why not give names to the packing (arrangment, really ) strategies ?
The default strategy would be good for packing bit fields, being
clever about inheritance, etc., while others would have definite,
documented implications for the bitwise arrangement of members.
--
Robert P. Krajewski
Internet: rpk@ai.mit.edu ; Lotus: robert_krajewski.lotus@crd.dnet.lotus.com




Author: rminnich@super.ORG (Ronald G Minnich)
Date: 6 Aug 90 17:14:58 GMT
Raw View
In article <MCGRATH.90Aug3011039@paris.Berkeley.EDU> mcgrath@paris.Berkeley.EDU (Roland McGrath) writes:
>In article <1944@ux.acs.umn.edu> hopper@ux.acs.umn.edu (hopper) writes:
>>    Currently the methods of structure member ordering, and packing
>>   specifications are easy enough to figure out that you can easily write a
>>   structure that models some hardware/OS data structure rather well.

Boy, talk about a bad case of deja vu. A long time ago, there was an
interesting little systems programming language. It allowed you to define
data structures and lay them out exactly as they would have to be layed out
in memory. If the machine you were on could not handle odd addresses it was
your responsibility to pad the structures yourself. As it happened it was
just terrific for writing OS code on minicomputers and things like that.
I assume you all can guess the name of this language.

We used to make fun of Pascal because you could define a structure in Pascal
but never really be sure of how it got laid out, unless of course you used
"packed" and kind of knew how the compiler laid things out and how
big the compiler assumed certain scalar types were and so on. Sound familiar?

>If you want to have a `struct' that corresponds to some hardware thing or
>whatever, and you know enough about the C compiler's padding conventions to do
>this, then write it inside `extern "C"' in C++.  This still doesn't guarantee
>you a damn thing as far as the standards are concerned.
>"We can't allow A in the standard because it makes it more difficult to do
>nonstandard, unportable hack B (which is not guaranteed by the standard to
>work, but which probably will most days of the week)" does not sound to me like
>a reasonable argument.

So, if i read this right, C (and hence its descendant, C++)
has moved so far from its origins as a systems programming language that
it is now useless for some things it used to be very good for, e.g. writing
device drivers.
Not only that, but that one particular use is being called a nonstandard,
unportable hack, whereas at one time (I know, maybe too long ago)
that was cited as a "case in point" for the power of the language.
This is progress?

I think that if C++ and/or C could somehow resolve this problem of
exact bit-by-bit specification of a structure, a problem which actually
has been solved many other times in other languages, that would enhance
its usefulness. And it would sure be nice if whatever comes out does not
have magic numbers like 16 or 32 hidden in it.
--
1987: We set standards, not Them. Your standard windowing system is NeUWS.
1989: We set standards, not Them. You can have X, but the UI is OpenLock.
1990: Why are you buying all those workstations from Them running Motif?




Author: ewiles@netxcom.DHL.COM (Edwin Wiles)
Date: 31 Jul 90 17:55:14 GMT
Raw View
In article <56165@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>Proposed:
>
>We need a way to "pack" objects over inheritence boundaries, and possibly
>between labeled fields of a declaration.  I do not propose here exactly
>what the "right" way to do this is.

[edited for brevity]

>Possible full or partial "solutions" to this problem include:
>
>* Throw out the current C++ restrictions on field ordering entirely.  What
>does it buy us anyway?  Use 'extern "C"' where an object needs backwards
>compatibility to "C" packing order.
>* Require current field ordering restrictions be maintained on things declared
>"struct", but removed restrictions on anything declared "class."

Let's see if I understand what you're proposing in the above two options.

I get the idea that what you want is to have the compiler be able to
assemble the fields in the classes in any order, rather than strictly
in the order in which they were defined.  Which *would* allow you to
pack bit fields together in the way you want, however....

I would argue against both of the above as a 'default' for the following
reasons:

 A) You would not be guaranteed that a data file written by a given
 program on one machine, would be readable by the same program compiled
 on a different machine under a different implementation of C++.
 (Assuming that hardware and byte ordering are the same, the order
 of structure/class elements wouldn't necessarily be the same.)

 B) Certain C++ languages (Lattice C++ for the Amiga for one) make
 extensive use of C++ structures/classes to hide the cruft of working
 with the system libraries.  Surely a desireable end.  However, the
 system libraries depend on a specific order of elements within a
 structure and would likely break under either of the above.

>* Introduce an explicit keyword "packed" or similar.  Declaring a base class
>"packed" turns off field ordering restrictions in that class and its
>derivatives, as well as representing a directive to the compiler that small
>size is to be preferred to fast access.  Possibly vtable ptrs could also
>be replaced with smaller type tags in such classes....

This would be more acceptable, as it leaves it as an option that the programmer
can use if appropriate, but doesn't force the issue.  However, it could still
have the problems shown above, and should therefore NOT be used where
portability is important.  If the structure/class is purely internal, never
appearing outside of the program in question, then it's acceptable.

At least not until the order and method of packing items is agreed upon
by the C++ industry, and preferably by the C compiler writers as well!

[disclaimer: this posting respresents the opinions of an individual C++ user]




Author: johnb@srchtec.UUCP (John Baldwin)
Date: 31 Jul 90 18:47:42 GMT
Raw View
In article <56165@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>Proposed:
>We need a way to "pack" objects over inheritence boundaries, and possibly
>between labeled fields of a declaration.
>...[excerpted]....

>* Require current field ordering restrictions be maintained on things declared
>  "struct", but removed restrictions on anything declared "class."

Personally, I like this option best.  On an entirely subjective level, it is
in keeping with the philosophy of C++ being "extended/better C", and it would
minimize confusion when switching often between writing C and C++.

[disclaimer: just another user's comments on the first user's suggestion.]
--
John T. Baldwin                      |  johnb@srchtec.uucp
Search Technology, Inc.              |  johnb%srchtec.uucp@mathcs.emory.edu
standard disclaimer:                 |  ...uunet!samsung!emory!stiatl!srchtec..
opinions and mistakes purely my own. |  ...mailrus!gatech!stiatl!srchtec...




Author: rfg@NCD.COM (Ron Guilmette)
Date: 31 Jul 90 22:52:38 GMT
Raw View
In article <56165@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>Proposed:
>
>We need a way to "pack" objects over inheritence boundaries, and possibly
>between labeled fields of a declaration.  I do not propose here exactly
>what the "right" way to do this is.
>
>I claim this is important because I see lots of examples of serious C++
>programmers implementing "hacks" to "pack" objects across inheritence
>boundaries.  Examples include:  Base class B needs two bits, and derived
>class D needs three bits, so let's implement a bit sharing hack between
>base and derived...

It's an obvious and serious problem. Yes.

>... Features commonly used should be
>part of the language, not implemented via "hack" word-arounds.

Quite so.

>Possible full or partial "solutions" to this problem include:
>
>* Throw out the current C++ restrictions on field ordering entirely.  What
>does it buy us anyway?

If you mean the rule that says that all protected members get clumped together
(despite my best efforts and intentions, and no matter what I would prefer)
then yes.  This restrictive and irritating rule should be thrown out.

What ever happened to the philosophy that says that the programmer knows
what he want's, so (unless it obviously stupid *and* dangerous) let him
do what he wants?

>Use 'extern "C"' where an object needs backwards
>compatibility to "C" packing order.

Huh?

>* Require current field ordering restrictions be maintained on things declared
>"struct", but removed restrictions on anything declared "class."

Bad idea.

>* Introduce an explicit keyword "packed" or similar.  Declaring a base class
>"packed" turns off field ordering restrictions in that class and its
>derivatives, as well as representing a directive to the compiler that small
>size is to be preferred to fast access.  Possibly vtable ptrs could also
>be replaced with smaller type tags in such classes....

Since the issue involves the boundary between a derived class and exactly
one of its base classes, I suggest that perhaps "packed" should be a way
of doing inheritance, e.g.:

 class doe : public rea, packed public me { ... };

would specify that the earliest field of `doe' should get packed up against
the latest field of `me'.


--
// Ron Guilmette
// C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.




Author: jeremy@cs.ua.oz.au (Jeremy Webber)
Date: 31 Jul 90 23:13:11 GMT
Raw View
In article <6785@netxcom.DHL.COM> ewiles@netxcom.DHL.COM (Edwin Wiles) writes:

    A) You would not be guaranteed that a data file written by a given
    program on one machine, would be readable by the same program compiled
    on a different machine under a different implementation of C++.
    (Assuming that hardware and byte ordering are the same, the order
    of structure/class elements wouldn't necessarily be the same.)

The ability for a compiler to re-order the elements of structures/unions is a
useful optimization.  I would argue that any code which writes structures to
a data file is non-portable.  If data is to be portable it should *always* be
written element by element, preferably in ASCII.  The programmer should never
assume specific structure ordering, except in the case of bit field
specifications, which can override the compiler's defaults.

This is the sort of hackery which causes many C programs to fail!
--
--
Jeremy Webber      ACSnet: jeremy@chook.ua.oz
Digital Arts Film and Television,  Internet: jeremy@chook.ua.oz.au
60 Hutt St, Adelaide 5001,    Voicenet: +61 8 223 2430
Australia      Papernet: +61 8 272 2774 (FAX)




Author: Chuck.Phillips@FtCollins.NCR.COM (Chuck.Phillips)
Date: 1 Aug 90 08:05:47 GMT
Raw View
>>>>> On 31 Jul 90 23:13:11 GMT, jeremy@cs.ua.oz.au (Jeremy Webber) said:
Jeremy> The ability for a compiler to re-order the elements of
Jeremy> structures/unions is a useful optimization.  I would argue that any
Jeremy> code which writes structures to a data file is non-portable.

True.  Even if the ordering is identical, the alignment may vary.  However,
alignment is not _likely_ to vary between systems using the same CPU,
although it still _can_ vary due to compiler differences.

Jeremy> If data is to be portable it should *always* be written element by
Jeremy> element, preferably in ASCII.

If your program isn't already I/O bound, this is an excellent strategy, and
I highly recommend it as the default strategy.

Jeremy> The programmer should never assume specific structure ordering,
Jeremy> except in the case of bit field specifications, which can override
Jeremy> the compiler's defaults.

Even this can fail, unless all the world is a 32 bit int.  Seriously, many
programs have to bang hardware which may not pack data in the "optimized"
form.  Perhaps this (and portability between compilers) is partly why order
of inheiritance became defined under C++ 2.0.

I also suspect reordering members between parents in a derived class such
that their elements are interleaved, would present a run time nightmare for
the C++ implementor.  Perhaps one of the implementors out there would care
to comment.

Jeremy> This is the sort of hackery which causes many C programs to fail!

...and many operating systems to work.

#pragma STD_DISCLAIMER
--
Chuck Phillips  MS440
NCR Microelectronics    Chuck.Phillips%FtCollins.NCR.com
Ft. Collins, CO.  80525     uunet!ncrlnk!ncr-mpd!bach!chuckp




Author: henry@zoo.toronto.edu (Henry Spencer)
Date: 1 Aug 90 17:11:48 GMT
Raw View
In article <6785@netxcom.DHL.COM> ewiles@netxcom.DHL.COM (Edwin Wiles) writes:
> A) You would not be guaranteed that a data file written by a given
> program on one machine, would be readable by the same program compiled
> on a different machine under a different implementation of C++.

This is already the case, and is not likely to change.  The internal format
of structs/classes typically contains machine-specific padding, which isn't
always the same even between machines using the same processor (680x0 systems
differ!), never mind seriously-different machines.  There are also the small
issues of byte ordering, floating-point representation, ones-complement
integers, etc.  The "guarantee" that you are claiming has never existed.

> B) Certain C++ languages (Lattice C++ for the Amiga for one) make
> extensive use of C++ structures/classes to hide the cruft of working
> with the system libraries.  Surely a desireable end.  However, the
> system libraries depend on a specific order of elements within a
> structure and would likely break under either of the above.

This just means that there have to be enough guarantees on behavior that
the library code can assume a stable base.  This is much the same as what
would be needed to make inheritance work anyway, so I don't see a problem
there in general.
--
The 486 is to a modern CPU as a Jules  | Henry Spencer at U of Toronto Zoology
Verne reprint is to a modern SF novel. |  henry@zoo.toronto.edu   utzoo!henry




Author: elw@netxcom.DHL.COM (Edwin Wiles)
Date: 1 Aug 90 22:44:54 GMT
Raw View
In an article jeremy@cs.ua.oz.au (Jeremy Webber) writes:
>In an article ewiles@netxcom.DHL.COM (Edwin Wiles) writes:
>>
>> A) You would not be guaranteed that a data file written by a given
>> program on one machine, would be readable by the same program compiled
>> on a different machine under a different implementation of C++.
>> (Assuming that hardware and byte ordering are the same, the order
>> of structure/class elements wouldn't necessarily be the same.)
>
>The ability for a compiler to re-order the elements of structures/unions is a
>useful optimization.

Granted, it has it's uses.  So I'm in favor of having a "packed" keyword
which instructs the compiler to rearrainge the structures as appropriate,
but against making such rearraingment the default.

>I would argue that any code which writes structures to a data file is
>non-portable.  If data is to be portable it should *always* be written
>element by element, preferably in ASCII.

I work in the real world (presumably you do too), and in the real world you
don't always have enough file space to store data in 'ascii' format.  (And you
can't always "throw hardware at the problem" either!)  Nor do you have the time
that is required to write and debug thirty or more 'read/write' statements for
every one of your data structures.  THAT is wasted effort.  Far quicker and
simpler to write the data structure itself out.

Unfortunately, although I use C++ on my home computer, I haven't been able to
convince work to switch over, and even when I do, they will NOT allocate the
time required to rewrite all the old code.  This means that when/if we switch
to C++ for our new code, the data it writes MUST be compatible with the
existing code, who's data files ARE portable to a number of machines, and which
DOES use structures for reading and writting data.

>The programmer should never
>assume specific structure ordering, except in the case of bit field
>specifications, which can override the compiler's defaults.

Now that is just sooo much malarky.

No C compiler that I know of rearranges the order of elements in a structure.
Some of them adjust to 2 byte boundaries, and some to 4, due to hardware
considerations, but NONE of them change the order of the data as specified by
the source.

>This is the sort of hackery which causes many C programs to fail!

Never done it to me!  If it has to you, then I suggest that there are
compiler writers out there who are puting in "features" which are most
definitely non-standard.  Any non-standard feature should NOT be the
default but should instead be used only by the express wish of the user.

     Later!
      Edwin.




Author: mcgrath@paris.Berkeley.EDU (Roland McGrath)
Date: 2 Aug 90 05:58:52 GMT
Raw View
In article <6815@netxcom.DHL.COM> elw@netxcom.DHL.COM (Edwin Wiles) writes:

   >I would argue that any code which writes structures to a data file is
   >non-portable.  If data is to be portable it should *always* be written
   >element by element, preferably in ASCII.

   I work in the real world (presumably you do too), and in the real world you
   don't always have enough file space to store data in 'ascii' format.  (And
   you can't always "throw hardware at the problem" either!)  Nor do you have
   the time that is required to write and debug thirty or more 'read/write'
   statements for every one of your data structures.  THAT is wasted effort.
   Far quicker and simpler to write the data structure itself out.

Fine.  Do it.  Just don't expect the data files to be portable.  That's all.

   Unfortunately, although I use C++ on my home computer, I haven't been able
   to convince work to switch over, and even when I do, they will NOT allocate
   the time required to rewrite all the old code.  This means that when/if we
   switch to C++ for our new code, the data it writes MUST be compatible with
   the existing code, who's data files ARE portable to a number of machines,
   and which DOES use structures for reading and writting data.

As I said, this is why we have `extern "C"'.  If certain structures need to be
done compatibly, declare them inside `extern "C"', and they will be done just
as the C compiler does them (not that this gives you any measure of portability
across different machines, operating systems, compilers, or compilation-time
command-line flags).

   >The programmer should never
   >assume specific structure ordering, except in the case of bit field
   >specifications, which can override the compiler's defaults.

   Now that is just sooo much malarky.

   No C compiler that I know of rearranges the order of elements in a
   structure.  Some of them adjust to 2 byte boundaries, and some to 4, due to
   hardware considerations, but NONE of them change the order of the data as
   specified by the source.

Well, good!  Then when you make your strucutre declarations inside `extern "C"'
you won't have any problems.  Outside of `extern "C"', we're talking about a
different language, however.

   >This is the sort of hackery which causes many C programs to fail!

   Never done it to me!  If it has to you, then I suggest that there are
   compiler writers out there who are puting in "features" which are most
   definitely non-standard.  Any non-standard feature should NOT be the
   default but should instead be used only by the express wish of the user.

Agreed.  However, we are talking about the standard for C++.  As this standard
remains to be defined, and is independent from the existing standard for C,
I don't see the relavence of your statement.
--
 Roland McGrath
 Free Software Foundation, Inc.
roland@ai.mit.edu, uunet!ai.mit.edu!roland




Author: gjditchfield@watmsg.uwaterloo.ca (Glen Ditchfield)
Date: 2 Aug 90 14:24:10 GMT
Raw View
In article <MEISSNER.90Aug1191316@osf.osf.org> meissner@osf.org (Michael Meissner) writes:
>Also, it would seem to me that reordering things across class
>boundaries is a really bad idea -- then subclassing and virtual
>functions would have no chance of working.

In article <MCGRATH.90Aug1231443@paris.Berkeley.EDU> mcgrath@paris.Berkeley.EDU (Roland McGrath) writes:
>If it is not feasible to reorder members across class boundaries and still do
>subclassing and virtual functions right then no one will try to do it in their
>implementation.  That doesn't mean the standard should prevent people from
>trying if they want to.

Reordering does not have to go so far as to change the offsets of inherited
members.  The rule could be that new members can be placed in holes left by
padding in the superclass or in unused portions of storage units that
contain inherited bitfields.  I think this would do all the packing that
Jim Adcock originally wanted, without affecting current implementations of
inheritance.
   Since nothing in C corresponds to class inheritance, I don't see that
this introduces any incompatibility, either.  If you declare a struct, it
would be laid out just like a C struct.

    Glen Ditchfield  gjditchfield@violet.uwaterloo.ca  Office: DC 2517
Dept. of Computer Science, U of Waterloo, Waterloo, Ontario, Canada, N2L 3G1
       These opinions have not been tested on animals.