miron@fornax.UUCP (Miron Cuperman) (08/16/90)
Is the order of fields within a section preserved?
For example:
class C
{
private:
int size;
float a[0];
}
Is 'a' guaranteed to be after size so I can do
C *C1=malloc(sizeof(C)+n*sizeof(float));
If that is permissible, is it possible to use 'new' to allocate
an arbitrarily sized object?
--
By me: Miron Cuperman <miron@cs.sfu.ca>perry@key.COM (Perry The Cynic) (08/18/90)
In article <1083@fornax.UUCP> miron@fornax.UUCP (Miron Cuperman) writes: > Is the order of fields within a section preserved? > For example: > class C > { > private: > int size; > float a[0]; > } > > Is 'a' guaranteed to be after size so I can do > C *C1=malloc(sizeof(C)+n*sizeof(float)); > > If that is permissible, is it possible to use 'new' to allocate > an arbitrarily sized object? The order of fields within a section is guaranteed to be preserved by the compiler (says E&S). You are guaranteed that "a" follows "size" in the storage layout of the class. But that doesn't help you. The compiler is perfectly entitled to place stuff *after* a[0] (there is an explicit warning to that effect in E&S) If class C has virtual members, you have a good chance that some compiler out there (perhaps yours) will put its virtual table pointer at the end of the class, totally screwing up your scheme. This is not portable C++, nor is it good C++, though it is a common practice in the C world. One possible solution is to change your class definition into class C { public: C(int n); private: int size; float *a; }; C::C(int n) { a = new float[n]; } which is (I hope) perfectly portable. You can add appropriate access functions to your class (including, if you wish, a float& operator[]). Depending on your particular situation, you may then be able to allocate objects of type C as static or auto variables, or members of other structures. If you can do that, performance will actually be improved (because accesses to the size member don't need indirection). This requires a somewhat different way to look at C objects (value-oriented vs. reference-oriented), but I find it to be rather useful. -- perry -- -------------------------------------------------------------------------- Perry The Cynic (Peter Kiehtreiber) perry@arkon.key.com ** What good signature isn't taken yet? ** {amdahl,sgi,pacbell}!key!perry
jimad@microsoft.UUCP (Jim ADCOCK) (08/18/90)
In article <1083@fornax.UUCP> miron@fornax.UUCP (Miron Cuperman) writes: >Is the order of fields within a section preserved? Yes. According to E&S. But, "preserved" only means that fields declared later within a section come at higher addresses. "Preserved" doesn't mean that fields are adjecent, nor that they don't have anything else useful between them, nor that they have the same packing characteristics as your favorite C compiler. [Although I'd certainly think that most vendors would want to keep their C and C++ compilers pretty compatible for the next couple of years as people switch over.] But, I'm lobbying to have this restriction eased so that C++ compilers aren't constrained to be backwardly compatible with C a couple years down the road -- when backwards compatibility is no longer an issue. And again, in any case, for a C and a C++ compiler to be "compatible" a vendor is going to have to make a conscious decision they want their C and C++ compilers to be compatible. Field ordering is only a tiny part of this decision. Removing field ordering restrictions doesn't keep a vendor from making their C and C++ compilers compatible. Maintaining field ordering doesn't force a vendor to keep their C and C++ compilers compatible. In either case, its still strictly an particular vendor's choice. So I say, let's remove this silly restriction. >For example: >class C >{ >private: > int size; > float a[0]; >} No -- Array dimensions must be specified as being greater than zero. >Is 'a' guaranteed to be after size Yes -- but "after" just means that a has a higher address than size, not that they are next to each other. And what it means to compare addresses of different types of things is also undefined. So what does it mean to be able to say a is "after" size ? so I can do C *C1=malloc(sizeof(C)+n*sizeof(float)); Yes and No. Yes such a statement is legal in the language. But, no it is not legal to then use C1 as you're planning to use it. E&S specifically calls out the old C trick of writing off the end of a structure as being illegal. [It was never even legal to write off the end of an array in C] Most C++ compilers today would generate code incompatible with this hack if someone subsequently tries to derive from class C. >If that is permissible, is it possible to use 'new' to allocate >an arbitrarily sized object? "That" is not "legal" --but is it "permissible"? Most C++ compilers will permit you to get away with it [given your array index is not zero.] Just don't try to derive from C, nor make an instance static, nor put an instance on the stack.... ....The obvious hack is to get a chunk of memory from new: void *pv = new char[sizeof(C) + n*sizeof(float)]; // give or take one from n then construct your object at the start of that chunk using placement syntax: C* C1 = new(pv) C(n); --- Better yet, just don't do this hack, use a separate allocation for your array.