I just had a similar problem and after days of hacking and reading the C++
standard carefully again
I found the following that might be your basic problem (and which has
nothing to do with
ClassDef() macros, but with interpreted versus compiled code!).
In C++ the size of a class, struct and union is *NOT* necessarily equal the
sum of bytes
of its members!! That means a C++ compiler/interpreter is allowed to assign
any size
it wants to following struct (same for class and union)
struct Test_t {
Char_t c;
Short_t i;
} testStruct;
Naively (and rightly so) you would expect to get a sizeof(testStruct) = 3.
This you will get e.g. with the gcc compiler and default flags.
HOWEVER a compiler is free to assign ANY size it wants (in practice
they often align the struct boundaries on multples of 8 bytes for efficiency
reason -
so does e.g. the Microsoft VC++ compiler by default), i.e. they "pad" the
testStruct (of
naive size 3) with 1 or even 5 bytes!! Therefore an array of structs, e.g.
Test_t testArray[10];
will be 80 bytes long instead of 30 (with 5 byte gaps between each struct
element).
This is exactly the case with the CINT interpreter. On my (WinNT and
Sun/Solaris) versions
CINT assigns 8 bytes to above struct:
root [0] struct Test_t { Char_t c; Short_t i;} testStruct
root [1] sizeof(testStruct)
(int)8
root [2] Test_t testArray[10]
root [3] sizeof(testArray)
(int)80
BOTTOM LINE:
You CANNOT assume sizeof(struct/class/union) = sum of member sizes!!!
If code relies on this (because it happens to work on one compiler) it is
certainly not
portable.
You *CANNOT* EQUIVALENCE/union a C++ class/struct with a continuos
storage (fortran or
C/C++) array in a portable manner! (I fell into this pitfall too).
It is ANSI-C++'s fault not ROOT/CINT's (the latter apparently chooses the
most efficent 8-byte alignment...).
If you want to read a fortran array into a class you have to copy
member-by-member from the appropriate
array elements in a loop.
So far my experience with that alignment ambiguity problem.
Now a question to CINT experts:
Most compilers have a switch to turn "struct/class/union-alignments" on/off
or to specific value (2,4, 8).
I haven't found any similar option for CINT. Is there a switch for CINT ????
Also, is there a way to define a certain aligment choice for a specific
struct and another one for the next struct/class
(I am thinking/hoping of some #pragma switch) ??
Even if not required by the C++ standard, it would be nice to have...
Thanks in advance
Peter
----- Original Message -----
From: Maurik Holtrop <maurik.holtrop@unh.edu>
To: roottalk <roottalk@hpsalo.cern.ch>
Sent: Thursday, May 20, 1999 11:47 AM
Subject: ClassDef() Increases class size?
> Hello Root,
>
> I seem to be running into a problem with ClassDef (and ClassImp)
increasing
> the size of my class's storage area by about 4 bytes. I am *not* deriving
> from TObject, so the extra bytes are not from there.
> Is there a way around this which will still give me all the nice features
> (streamer, showmember etc) of ROOT but keep my class the exact same size
as
> the data members I defined?
>
> The reason that the extra bytes are a problem is because I am setting
> pointers into an already existing array with data (which is created by a
> FORTRAN package called BOS), in order to read it's contends. The extra
bytes
> causes the next pointer to be 4 bytes off.
>
> Maurik
>
>
> --------------------------------------------------------------------------
-------
>
> Sample code:
>
> The following code will have a "sizeof()" of 56 instead of the expected
52:
>
> class TPARTData {
> public:
> Int_t pid; /* particle id
> (GEANT) */
> Float_t x; /* vector3_t vert; Vertex position
> {x,y,z} */
> Float_t y; /*
> y */
> Float_t z; /*
> z */
> Float_t e; /* vector4_t p;
> Energy */
> Float_t px; /* momentum
> {x,y,z} */
> Float_t py; /*
> py */
> Float_t pz; /*
> pz */
> Float_t q; /*
> charge */
> Int_t trkid; /* index to TBID bank, counting
from
> 1 */
> Float_t qpid; /* quality factor for the
> pid */
> Float_t qtrk; /* quality factor for the
> trk */
> Int_t flags; /* set of flags defining track (ie,
> BEAM) */
>
> ClassDef(TPARTData,1)
>
> };
>
>