[comp.std.c] forbidden? unnecessary?

maart@cs.vu.nl (Maarten Litmaath) (12/09/89)

In article <15364@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
\...  It seems to me that
\	typedef struct { junk_t xx; char name[1]; } T;
\	T *p = (T *)malloc(sizeof(T) + strlen(s));
\	strcpy(p->name, s);
\is legal and portable, and I believe I can rigorously prove it from the rule
\"objects are composed of bytes":
\
\0.  The result of malloc() is an aligned chunk of sizeof(T)+strlen(s) bytes
\
\1.  Casting such into a (T *), and then back into a (void *), yields the same
\    result (else free() wouldn't work; see recent commentary in this group!)

But couldn't an conforming implementation FORBID the (T *) cast?!
(Stepping aside from the problems of indexing p->name beyond its end.)
Suppose every piece of memory were tagged with a specification of what kind
of object it belongs to, e.g.:

	- object starts at address x
	- object's size is y bytes
	- object's type is z

Furthermore let the compiler check the `sensibility' (legality) of each cast,
at compile time if possible, else at run time (i.e. extra code is generated
or the run time system itself does the checking).
Whatever, the following could be detected:

	the cast to (T *) conflicts with malloc()'s argument!

malloc() returns an object of `the wrong' size.
Anyway, I think the abovementioned is the only thing that could be wrong with
the following alternative:

	typedef struct { junk_t xx; char *name; } T;
	T *p = (T *)malloc(sizeof(T) + strlen(s) + 1);
	strcpy(p->name = (char *)p + sizeof(T), s);

If this method is used, copying the struct pointed to by p won't have strange
effects, as long as *p isn't free()d.  Regarding the struct dirent example
I'd call that an improvement.
-- 
"Engineering induction:  if it works for n = 1, 2, and 3, that's good enough
for me".  (Ric Hehner)              | maart@cs.vu.nl, uunet!mcsun!botter!maart

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/09/89)

In article <4749@fireball.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>But couldn't an conforming implementation FORBID the (T *) cast?!

No, a conforming implementation is obliged to accept a strictly
conforming application.  It cannot impose its own additional
constraints beyond those spelled out in the Standard.

>	strcpy(p->name = (char *)p + sizeof(T), s);
>If this method is used, copying the struct pointed to by p won't have strange
>effects, as long as *p isn't free()d.  Regarding the struct dirent example
>I'd call that an improvement.

Hardly.  The declared object T does not contain all of the information;
the "name" data lies outside the T object.  This is as bad as the case
that Dennis objected to so far as its usability goes (apart from
linguistic correctness issues).