sizeof a struc field

Wm E Davidsen Jr davidsen at crdos1.crd.ge.COM
Thu Oct 19 05:21:57 AEST 1989


In article <11316 at smoke.BRL.MIL>, gwyn at smoke.BRL.MIL (Doug Gwyn) writes:

|  I said that dereferencing a null pointer CONSTANT was meaningless,
|  and it is EXACTLY the kind of thing I want compilers to check for
|  me at compile time.  

But the pointer is not being dereferenced. A pointer can't be
dereferenced at compile time.

Examples which work with pcc and gcc and appear valid as I read the standard:
(1)	int *foo = (int *)0;
	int bar = sizeof(*foo);

(2)	void test(x)
	  struct mytype *x;
	{
	  int m = sizeof(x->a);		/* x certainly could be NULL */
	}

  Now the pointer foo is not being dereferenced, sizeof a pointer with
an indirect is evaluated by taking the size of the type of the object to
which the pointer *may* validly point. This is done at compile time,
asis example (2), where the type of field a within struct mytype is used
to set the initializer.

What the original poster wanted was the size of a field within a struct.
He proposed using:
	sizeof(((struct mytype *)0)->field)
which involves using a null values pointer. The value of this under pcc
compilers is the size of the field within a struct mytype. You interpret
the standard to forbid this.

Do you also interpret the standard to forbid:
	struct mytype {
	  int a, b;
	} *head = (struct mytype)0;
	int fieldlen = sizeof(head->a);

I would first note that sizeof always works on the *type* of the object.
Not only things like "sizeof(int)" but "sizeof(xyz)" must be done by
type, since xyz is not an allocated object at compile time, what is
really delivered by the sizeof operator is the size of the generic type
of xyz.

I realize that there are good reasons for not dereferencing NULL
pointers, but since the sizeof operator actually returns the size of
the *type* of the specified object, I certainly can't see any technical
reason why the original construct should be rejected, since the type
information is available at compile time, and the value of the pointer
is not. The compiler can't validate the value of the pointer in any
other case, why should it be required or even allowed to do so in this
case.

Here's what the standard says (3.3.3.4):

  The *sizeof* operator shall not be applied to an expression that has
function type or an incomplete type, to the parenthesized name of such a
type, or to an lvalue that designates a bitfield object.

  The *sizeof* operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is
determined by the type of the operand, which is not itself evaluated.
The result is an integer constant.

================ end quote ================

If the expression is not evaluated the pointer is not dereferenced and
there is no problem as far as hypothetical hardware which checks for
this. I see nothing which I can read to forbid the original construct
or indicate that it might not be valid in this case. The meaning of an
incomplete type is spelled out in 3.1.2.5 and a null pointer with a
cast isn't shown. I therefore conclude that the construct of the
original poster is valid C as specified by the standard. I also really
wonder why sizeof doesn't return "unsigned int" but I suspect i wouldn't
like the answer.

-- 
bill davidsen	(davidsen at crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon



More information about the Comp.lang.c mailing list