[net.lang.c] side effects inside sizeof

henry@utzoo.UUCP (Henry Spencer) (05/13/84)

Here's an entertaining oddity in C.  Try running the following under
your favorite C compiler:

----
main(){
	int x = 1;

	printf("%u\n", sizeof(x++));
	printf("%d\n", x);
}
----

The result of the first printf is uninteresting, just whatever the
size of an integer is on your machine.  The result of the second
printf is the good part.  Looks like x should have been incremented
by the autoincrement, so it should be 2.  Surprise -- on every system
handy locally, it's 1!  (This includes V7, 4.1BSD, 4.2BSD, Amdahl UTS,
and several varieties of 68K.)

The fact is, most C compilers don't generate code for the expression
inside sizeof at all.  Once they know what type it is, the result of
the sizeof is fully defined, so "of course" the details of the operand
no longer matter.  But nowhere in K&R is there anything that would
permit this wanton disregard of side effects, unless you really work
the statement "...this expression is semantically an integer constant..."
hard.

I agree that the behavior as implemented is reasonable and should be
classed as "correct", but this needs to be more explicitly documented.
Anybody know whether the ANSI C committee has noticed this one?
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

dmmartindale@watcgl.UUCP (Dave Martindale) (05/13/84)

Another interesting one is:

#define MSG "this is some string or other"

...

	l = sizeof(MSG);

In the compilers I'm familiar with, the string is dumped out into
the data space of the program, even though the compiler does evaluate
the size at compile time and the string will never be referenced.

dan@idis.UUCP (Dan Strick) (05/14/84)

I would think it unreasonable to apply sizeof to anything that
does not name a storage area (i.e. is not an l-value). X++ is
not an l-value.

				Dan Strick
				[decvax|mcnc]!idis!dan

opus@drutx.UUCP (ShanklandJA) (05/15/84)

Joey Duhon (ihuxj!duhon) writes:

    On page 126 we read "The expression sizeof(object) yields an
    integer equal to the size of the specified object. ... The object can be
    an acutual variable or array or structure, ..."
    I don't see anything here about other expressions.
    The confusion seems to be over the reference manual which indicates
    that the grammar will accept "sizeof expression" syntactically.
    This is obviously a shortcut for the compiler writer(s).
    However, the semantic interpretation is explained above(p.126).

    This all seems clear to me.

Good point, but we've still got a compiler problem here, I'd say.
If sizeof( x++ ) is really a semantic error, then the compiler ought
to be complaining about it, rather than quietly doing its own thing,
whatever that may be.  Undeclared variables are also permitted by
the C syntax -- that is, they are a semantic error -- but I imagine
howls would be heard far and wide (mine certainly would be) if a C
compiler issued no error message for an undeclared variable, and issued
code that dumped core the first time that variable was referenced or
assigned to.

Jim Shankland
..!ihnp4!druxy!opus

duhon@ihuxj.UUCP (duhon) (05/15/84)

Having read all the speculation about what "sizeof expression" should
present, I thought I'd read the manual ("The C Programming Language,"
Kernighan and Ritchie).

On page 126 we read "The expression sizeof(object) yields an
integer equal to the size of the specified object. ... The object can be
an acutual variable or array or structure, ..."
I don't see anything here about other expressions.
The confusion seems to be over the reference manual which indicates
that the grammar will accept "sizeof expression" syntactically.
This is obviously a shortcut for the compiler writer(s).
However, the semantic interpretation is explained above(p.126).

As an aside, "Programming in C," by Kockan says the following:
"The argument to the sizeof operator can be a variable, an array name,
the name of a basic data type, or the name of a derived data type."

This all seems clear to me.
			Joey Duhon
			ihnp4!ihuxj!duhon

henry@utzoo.UUCP (Henry Spencer) (05/17/84)

Joey Duhon says, in part:

   Having read all the speculation about what "sizeof expression" should
   present, I thought I'd read the manual ("The C Programming Language,"
   Kernighan and Ritchie).

   On page 126 we read "The expression sizeof(object) yields an
   integer equal to the size of the specified object. ... The object can be
   an acutual variable or array or structure, ..."
   I don't see anything here about other expressions.
   The confusion seems to be over the reference manual which indicates
   that the grammar will accept "sizeof expression" syntactically.
   This is obviously a shortcut for the compiler writer(s).
   However, the semantic interpretation is explained above(p.126).

All this is quite true, and I was aware of page 126.  But the definition
of the language is the C Reference Manual, ***NOT*** the textbook that
happens to precede one particular edition of it.  All page 126 tells us
is what DMR *intended*, but that's been clear all along anyway.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

ado@elsie.UUCP (06/16/84)

Here are additions to "/usr/src/cmd/mip/trees.c" (as distributed with 4.1bsd)
to detect side effects inside sizeof and issue a warning.
Since the usual licensing restrictions apply, I'll be vague.

1.  After the declarations in a function named "doszof", add these lines:

	#ifndef OLDVERSION
		if (haseffects(p))
			werror( "operations in object of sizeof are skipped" );
	#endif

2.  Right after the function names "doszof", add these lines:

	#ifndef OLDVERSION
	static int	haseffects(p)
	register NODE *	p;
	{
		register	o, ty;

		o = p->in.op;
		ty = optype(o);
		if (ty == LTYPE)
			return 0;
		if (asgop(o) || callop(o))
			return 1;
		if (haseffects(p->in.left))
			return 1;
		if (ty == UTYPE)
			return 0;
		return haseffects(p->in.right);
	}
	#endif

If you're truly into portability, you can arrange for something more severe than
a warning.
--
	...decvax!allegra!umcp-cs!elsie!ado	(301) 496-5688

EGADS!  All these months of giving an address that includes "decvax" and
I've failed to always note that the VAX in decvax is a Digital Equipment
Corporation trademark.  Please, DEC, hold off on the lawsuit--I plan to reform.

henry@utzoo.UUCP (Henry Spencer) (06/20/84)

I fully agree that my side-effects-of-sizeof program was an abomination,
and I wasn't "grumbling" about the second printf producing a "1" so much
as I was grumbling about the fact that the manual doesn't actually permit
this (eminently sensible) behavior.  The compilers are *not* broken, the
manual is.

I'm told that the draft ANSI C standard now includes specific words to
the effect that sizeof is fully compile-time and side effects don't
occur.  Good.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

addw@root44.UUCP (Alain Williams) (06/28/84)

<<<<<To be eaten by mailers>>>>>
Henry Spencer @ U of Toronto Zoology produced the following abomination:
main(){
	int x = 1;

	printf("%u\n", sizeof(x++));
	printf("%d\n", x);
}

He grumbles that the second printf produces a result of "1", & comments:
>> But nowhere in K&R is there anything that would
>> permit this wanton disregard of side effects,
But there is "nowhere in K&R is there anything that would" suggest that
the compilers are to be proof against all idiots. If one tries hard enough
it is possible to find pathological cases that break almost anything. Indulging
in such exercises is something that I enjoyed as an undergraduate, but have
since grown out of. I now try & USE the tools that I have.
	Alain Williams,
	Root Computers Ltd, London.
	{ENGLAND}!hirst1!root44!addw
	edai!root44!rootis!addw
	ukc!root44!addw