[comp.std.c] call to revolt

rabson@physics.ubc.ca (David Rabson) (06/25/91)

Until now, I have been content to sit back and ignore the ansi standard
for C.  Trigraphs are amusing -- I'm almost surprised the IBM representatives
on the committee didn't push for including computed gotos as well -- but
most compilers turn them off.  Eliminating the IDENTA/**/IDENTB concatenation
mechanism from the preprocessor was stupid but not enough to make me
post to this group.  (I am aware of the argument that supports the action,
tokenizing compilers, but I am not convinced by it).

Outlawing lvalue casts, however, borders on fascism.  I have yet to see
a pre-ansi compiler that fails to treat properly

		void *thing;
		((int *)thing)++;

(or, if it doesn't know about voids, the same thing with char *thing).  I
realize that some machines might, in principle, have different alignments for
different types of pointers.   A void *, however, I thought, was guaranteed
to obey the most restrictive alignment and hence be castable to any other
pointer.

I hereby invite the black-shirts from the ansi camp to explain their
prejudice against casting lvalues.

The rest of us should stop sitting back and start fighting.  If enough
customers insist on casting lvalues and otherwising ignoring ansi's
meddling in Kernighan's and Ritchie's work, vendors will create
correct, rather than compliant, compilers.

David Rabson
Departments of Physics, University of British Columbia and McMaster University

henry@zoo.toronto.edu (Henry Spencer) (06/26/91)

In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
>Outlawing lvalue casts, however, borders on fascism.  I have yet to see
>a pre-ansi compiler that fails to treat properly
>
>		void *thing;
>		((int *)thing)++;

What do you mean by "treat properly"?  What does this construct *mean*?
Remember that `void *' and `int *' need not even be the same size, much
less have the same representation.  A cast is a conversion operation,
not a "view these bits differently" operation.  (See K&R1 page 42.)

>The rest of us should stop sitting back and start fighting.  If enough
>customers insist on casting lvalues and otherwising ignoring ansi's
>meddling in Kernighan's and Ritchie's work, vendors will create
>correct, rather than compliant, compilers.

Please cite K&R chapter and verse for thinking that casts are lvalues.

You might also want to note that Dennis Ritchie has stated openly:
"I think X3J11 did an excellent job, though there are legitimate criticisms".
(Article <10039@alice.uucp>, 21 Oct 1989.)
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

sef@kithrup.COM (Sean Eric Fagan) (06/26/91)

In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
>Eliminating the IDENTA/**/IDENTB concatenation
>mechanism from the preprocessor was stupid but not enough to make me
>post to this group.  (I am aware of the argument that supports the action,
>tokenizing compilers, but I am not convinced by it).

How about this, then:  correct C preprocessors replace comments with white
space.  The Reiser cpp was *broken*, and many, many other implementations
existed that did not do that.

>Outlawing lvalue casts, however, borders on fascism.  I have yet to see
>a pre-ansi compiler that fails to treat properly
>
>		void *thing;
>		((int *)thing)++;

I can think of about 30.  Ok, an exaggeration, but I can name at least 5 or
6 that did not do this.

You can cast an lvalue.  However, the result is no longer an lvalue.  What
is a compiler supposed to make of:

	int f;
	(float)f++;

Learn the language.

-- 
Sean Eric Fagan  | "What *does* that 33 do?  I have no idea."
sef@kithrup.COM  |           -- Chris Torek
-----------------+              (torek@ee.lbl.gov)
Any opinions expressed are my own, and generally unpopular with others.

bhoughto@hopi.intel.com (Blair P. Houghton) (06/26/91)

In article <1991Jun25.181916.26586@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
>>Outlawing lvalue casts, however, borders on fascism.
>>		void *thing;
>>		((int *)thing)++;

And then I suppose the next line is

		((double *)thing)++;

>Remember that `void *' and `int *' need not even be the
>same size, much less have the same representation.  A cast
>is a conversion operation, not a "view these bits
>differently" operation.  (See K&R1 page 42.)

Much less the same location; after the cast the value may be
sitting in an accumulator, or in the phase space on the
wiring at 14.5 picoseconds antecedent to the accumulator
(Cray was a genius, kids, not just another hacker :-)),
but not necessarily anywhere near the storage for `thing'.

>Please cite K&R chapter and verse for thinking that casts are lvalues.

They certainly aren't addressable.

>>The rest of us should stop sitting back and start fighting.  If enough
>>customers insist on casting lvalues and otherwising ignoring ansi's

They'll be left behind.

I've seen other standards that have had _real_ problems in
them, and nobody bothers with them any more.  ANSI X3.159-1989,
on the other hand, is pretty solid, almost impervious.

				--Blair
				  "Write when you find a bug."

wittig@gmdzi.gmd.de (Georg Wittig) (06/26/91)

rabson@physics.ubc.ca (David Rabson) writes:


>		void *thing;
>		((int *)thing)++;

Why don't you write

	(*((int**)&thing))++;}

? gcc thinks it's o.k.
-- 
Georg Wittig   GMD-Z1.IT   P.O.Box 1240 | "Freedom's just another word
D-W-5205 St. Augustin 1	   (Germany)	|  for nothing left to lose"
email:		wittig@gmdzi.gmd.de	| (from "Me and Bobby McGee",
telephone:	(+49) 2241 14-2294	|  Janis Joplin, Kris Kristofferson)

jos@and.nl (J. Horsmeier) (06/26/91)

In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
[...]
>Outlawing lvalue casts, however, borders on fascism.  I have yet to see
>a pre-ansi compiler that fails to treat properly
>
>		void *thing;
>		((int *)thing)++;
>
>(or, if it doesn't know about voids, the same thing with char *thing).  I
>realize that some machines might, in principle, have different alignments for
>different types of pointers.   A void *, however, I thought, was guaranteed
>to obey the most restrictive alignment and hence be castable to any other
>pointer.
>
>I hereby invite the black-shirts from the ansi camp to explain their
>prejudice against casting lvalues.
[...]
>David Rabson
>Departments of Physics, University of British Columbia and McMaster University

Hi there, I'll die if casting lvals is going to be illegal. Currently I'm
fiddling and hacking my way into a FORTRAN (Yuck) program, trying to interface
the beast with loads of old C code. One of my most frequent statements is:

type* Thing;

((int)Thing)= Thing-Base+1;

where Thing points into an array of things and Base is the beginning of the
array, just to change pointers into FORTRAN indices. 
I know this is dirty and things might go into la la land on lots of 
machines, but it works on the machine it's running on now. 
I also know that I can overlay different types with unions. 

But why? Things used to work fine this way (if you know what you're doing). 
I really like the statement: `You get what you deserve'. Here I get what I
want :-) BTW beauty doesn't count when FORTRAN is involved. 

You have my support on this topic!

Jos


+----------------------------------------------------------------------+
|O   J.A. Horsmeier AND Software B.V.        phone : +31 10 4367100   O|
|O                  Westersingel 106/108     fax   : +31 10 4367110   O|
|O                  3015 LD  Rotterdam NL    e-mail: jos@and.nl       O|
|O--------------------------------------------------------------------O|
|O               I am a Hamburger (F. Zappa 1974)                     O|
+----------------------------------------------------------------------+

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/26/91)

In article <rabson.677868220@physics.ubc.ca>, rabson@physics.ubc.ca (David Rabson) writes:
> Outlawing lvalue casts, however, borders on fascism.  I have yet to see
> a pre-ansi compiler that fails to treat properly
> 
> 		void *thing;
> 		((int *)thing)++;
> 
> (or, if it doesn't know about voids, the same thing with char *thing).

Funny thing, I've been using C since V6+ UNIX (1979), and I have never
ever had any reason to use one of these things.  If you really want to
accomplish the probable intended effect of that,
	thing = (void*)(1+(int*)thing);
is legal, is it not?

> I hereby invite the black-shirts from the ansi camp to explain their
> prejudice against casting lvalues.

It was never part of the language, and this is an area where X3J11
chose not to innovate.

If you're going to moan about things which were never explicitly legal
vanishing, how about my old favourite?  Labels used to be usable as
constants of type char*, so I could pass a label in a C function to an
assembly-coded function.  Great for speeding up threaded-code.  But
did the ANSI committee support that lovely old hack?  No. Sob sob sob.
Do I call them "black-shirts" for this?  No.

> The rest of us should stop sitting back and start fighting.  If enough
> customers insist on casting lvalues and otherwising ignoring ansi's
> meddling in Kernighan's and Ritchie's work, vendors will create
> correct, rather than compliant, compilers.

It's attitudes like this that make me think about switching to Ada.

-- 
I agree with Jim Giles about many of the deficiencies of present UNIX.

fin@norge.unet.umn.edu (Craig A. Finseth) (06/26/91)

>>Outlawing lvalue casts, however, borders on fascism.  I have yet to see
>>a pre-ansi compiler that fails to treat properly
>>
>>		void *thing;
>>		((int *)thing)++;
	...
>Hi there, I'll die if casting lvals is going to be illegal. Currently I'm
>fiddling and hacking my way into a FORTRAN (Yuck) program, trying to interface
>the beast with loads of old C code. One of my most frequent statements is:
	...

Ok, kids, let's take a deep breath and say this one more time.  All
together now:

	The ANSI standard did not create any new illegal constructs.
	The ANSI standard only said, for the first time and in
	writing, that certain constructs WHICH NEVER WERE MEANINGFUL
	IN THE FIRST PLACE are, in fact, not meaningful.

Yes, some of these constructs may have worked on certain compilers in
certain situations.  THAT DOES NOT MEAN THAT THEY EVER WORKED ON ALL
COMPILERS IN ALL SITUATIONS IN THE PAST.  The fact that you may have
never bumped into one of these other compilers is irrelevant.  The
entire C world is not (pick your favorite) K&R-based, UNIX pcc-based,
IBM PC w/ Turbo C, IBM PC w/Microsoft C, a VAX, ...

So far, no one has come up with any examples of any of these
"meaningful" constructs that are, in fact, meaningful.  The recent
examples are:

		construct			rewrite as

	... ((i = 1) == (i = 2)) ...		(i = 1, 0) or (i = 2, 0)

	q = q++;				q = q + 1; or
						q += 1; or
						q++; or
						++q;

	void *thing;
	((int *)thing)++;			(*((int **)(&thing)))++;
						[ if you must, that is, and I
						hope that I got this right ]

My concluding advice?  If you find that you must use a construct like
the one on the left, you should refer to your favorite manual and find
the construct on the right that you really wanted in the first place.

Either that, or put in a comment of the form:

	/* The following construct is offically undefined.  However,
	on system ______ serial number _______ running OS ________
	version _______ release ______ configured as _____________
	_________________________________ and using compiler
	___________ version ________ release ________ with compilation
	flags __________ it just happens to work right.  For now.

	And, by the way, what I mean by "right" is ________________
	___________________________________________________________
	________________________________________________________ */

Now, do you see how much is gained by having a standard, following it,
and not trying to push the limits too much?

Craig A. Finseth			fin@unet.umn.edu [CAF13]
Networking Services			+1 612 624 3375 desk
Computer and Information Services	+1 612 625 0006 problems
University of Minnesota			+1 612 626 1002 FAX
130 Lind Hall, 207 Church St SE
Minneapolis MN 55455-0134, USA

roy@prism.gatech.EDU (Roy Mongiovi) (06/26/91)

Well, while I can think of easy ways to code around it, they involve extra
data movement.  I fail to see why the following should be categorically
outlawed:

	char *intptr;

	intptr = malloc(sizeof(int));

	read(fd, intptr, sizeof(int));

	*((int *) intptr)++;
		.
		.
		.

Admittedly, I can't think of a really great reason why I might want to
do that, but one of the major things that I like about C is that the
programmer is the boss.
-- 
Roy J. Mongiovi     Systems Support Specialist     Office of Computing Services
Georgia Institute of Technology	  Atlanta, Georgia  30332-0275   (404) 894-4660
	uucp: ...!{allegra,amd,hplabs,ut-ngp}!gatech!prism!roy
	ARPA: roy@prism.gatech.edu

steve@taumet.com (Stephen Clamage) (06/27/91)

jos@and.nl (J. Horsmeier) writes:

>In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
>[...]
>>Outlawing lvalue casts, however, borders on fascism.  I have yet to see
>>a pre-ansi compiler that fails to treat properly
>>		void *thing;
>>		((int *)thing)++;
>>I hereby invite the black-shirts from the ansi camp to explain their
>>prejudice against casting lvalues.

>Hi there, I'll die if casting lvals is going to be illegal...

Sorry your life has to end so soon, but it is not a question of "going
to be illegal", but "has always been illegal."  This rule is in K&R 1,
so it is nothing that the ANSI committee added out of sadism.  It is just
that many compilers failed to enforce the rule.

We have to differentiate between what works on some architectures and
what is suitable in a language definition.  Besides, you are only
presenting the trivial cases.  The issue is that a cast is a value
conversion, not just a request to treat a region of memory in a
different way.

Suppose a cast resulted in an lvalue whenever the object of the cast
were an lvalue.  Then this would be legal:
	float f;
	((double)f)++;
Nothing good could come of allowing code like this.  So we would have
to add an exception, like when the sizes were different.  Of course,
the representations might be different even when the sizes were the
same, so maybe that should be an exception too.  It turns into a
real mess.

The language already supports what you want to do, leaving in the
very proper semantic rule that a cast is a value conversion and
does not result in an lvalue.  To get the effect you want, just take
the address, cast the pointer, and dereference.
	void *thing;
	(*((int **)&thing))++;
This violates no language rules, so long as "thing" was assigned the
address of an int.  Otherwise, the code is not portable, but happens to
work on common architectures.  It is hard to write (and read), however.

If you do not have religious beliefs which require that ++ be used
whenever possible, you can write the above as
	thing = (int*)thing + 1;
which is legal, portable, and readable.  In the common case where the
illegal example would have been ok, the generated code should be identical
with any decent compiler.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

henry@zoo.toronto.edu (Henry Spencer) (06/27/91)

In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
>... I'll die if casting lvals is going to be illegal...

Sorry to hear of your demise.  Casts are not lvalues, and never have been,
despite an occasional sloppy compiler that let you get away with it.
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/27/91)

I don't understand. Is this whole ``call to revolt'' simply because
someone can't translate

   char *x;
   x += sizeof(int);

into void * terminology? Here goes:

   void *x;
   x = (void *) (sizeof(int) + (char *) x);

Sheesh. By the way, anyone who thinks that the ``safety'' of void *
outweighs the portability of char * must live in a very limited
environment. (An environment where you write code which only runs on one
machine fits my definition of limited.)

---Dan

gwyn@smoke.brl.mil (Doug Gwyn) (06/27/91)

In article <1991Jun25.190854.3327@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>Learn the language.

Hear, hear.  Just because X3J11 didn't do things the way that fellow would
have doesn't make X3J11 wrong and him right.  In this case, to the contrary.

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/27/91)

In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes:

>Hi there, I'll die if casting lvals is going to be illegal.

Well, you can cast an lval, but the result is not an lval.  I guess you
mean you'll die if the result of a cast isn't an lval.  I guess you've been
dead ever since casts were added to C, around 1978, except for brief intervals
on some BSD-based compilers.

>type* Thing;
>((int)Thing)= Thing-Base+1;

You'll die if you have to write
  Thing = (type*) (Thing-Base+1);
My heart bleeds for you.

Incidentally, your code would fail if int is smaller than pointers to "type,"
for example if int is 32 bits and pointers are 48 bits.  My suggestion would
fail if the implementation is excessively perverse, but not due to reasonable
hardware architectures.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/27/91)

In article <31822@hydra.gatech.EDU> roy@prism.gatech.EDU (Roy Mongiovi) writes:
>I fail to see why the following should be categorically outlawed:
>	char *intptr;
>	intptr = malloc(sizeof(int));
This is legal.

>	read(fd, intptr, sizeof(int));
This is also legal as far as the standard is concerned.  If you don't have
a prototype in scope, and size_t is not the same size of integer as read()
expects for its third parameter, then it could fail at execution time.

>	*((int *) intptr)++;

OK, if people want ++ to be applicable to non-lvalues, submit your suggestions
to the committee when they call for comments on C-2001 (the successor to
C-1989).  For all you people who enjoy doing:
    void f(int x) {
      x ++;
    }
    f(n);    /* Huh?  Why didn't the value of n get bumped? */
    f(3);    /* Huh?  Why didn't my 3 change to 4, like in the bad old
                 days of Fortran? */
OK, you should also be allowed to say
    (n + 13) ++;          /* Huh?  Why didn't n get bumped?  Or should
                              (n+13) have been bumped?  ?  */
    *((int *) intptr)++;  /* Huh?  Why didn't intptr get bumped? */
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

bhoughto@bishop.intel.com (Blair P. Houghton) (06/27/91)

In article <782@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>jos@and.nl (J. Horsmeier) writes:
>
>>In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
>>>		void *thing;
>>>		((int *)thing)++;
>
>	(*((int **)&thing))++;
>	thing = (int*)thing + 1;

This'll do it, too:

	thing += (int *)1;

(see ANSI X3.159-1989, sec. 3.3.16.2, p. 55, ll. 20-21, and
footnote 51 at the bottom of p. 51, for proof...)

				--Blair
				  "If void* was meant to fly,
				   X3J11 would have given it wings..."

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/27/91)

In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes:
>>>In article <rabson.677868220@physics.ubc.ca> rabson@physics.ubc.ca (David Rabson) writes:
>>>>		void *thing;
>>>>		((int *)thing)++;
>This'll do it, too:
>	thing += (int *)1;

Oh no, not again.  I thought addition of pointers had been beaten to death.

>(see ANSI X3.159-1989, sec. 3.3.16.2, p. 55, ll. 20-21, and
>footnote 51 at the bottom of p. 51, for proof...)

Well, the page numbers are different in the last draft version, and
footnote 51 has nothing to do with it, but I still see nothing that
hints at the legality of adding two pointers.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

bhoughto@bishop.intel.com (Blair P. Houghton) (06/27/91)

In article <1991Jun27.032834.13244@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>Oh no, not again.  I thought addition of pointers had been beaten to death.

Oh, screw it.

I'm going home and getting some sleep.

				--Blair
				  "If you'd just let me add
				   the damn pointers...did
				   I _ask_ for a lollipop???"

jos@and.nl (J. Horsmeier) (06/27/91)

In article <782@taumet.com> steve@taumet.com (Stephen Clamage) writes:
[...]
>>Hi there, I'll die if casting lvals is going to be illegal...
>
>Sorry your life has to end so soon, but it is not a question of "going
>to be illegal", but "has always been illegal."  This rule is in K&R 1,
>so it is nothing that the ANSI committee added out of sadism.  It is just
>that many compilers failed to enforce the rule.
[...]
>Steve Clamage, TauMetric Corp, steve@taumet.com

Hi there, 

I know, I know, you're absolutely right, and normally I don't diddle
code like I showed in my reply.
And I won't die either ... but, currently I am working on an interface
between *very* old C code and loads of FORTRAN stuff and I want to finish
this project asap. To plough through all this f*ckin' code makes my
mind go nuts, and invites one to fiddle/diddle these dirty tricks.

I know it's all *absolutely* non-portable, it's dirty and should not be done,
but I don't care in this particular case, I just want the thing up and running
on just one type of machine, and these kinda tricks allow me to hack things
together. 

I don't want to make a thread out of this, but I won't change my opinion
about the `you get what you deserve' philosophy. 
I like it, if I deserve non-portability, I want to get non-portability. 
If I deserve segmentation violations, I want to get segmentation violations. 
It's my own choice. I don't want any committee to forbid things like that 
in any language. A language is supposed to be a tool to express yourself, 
the way you want and like to do so :-) Restricting syntactic and/or semantic
richness of a language, just to avoid potential abuse by some zomby woofs
from outer space is bad practice IMHO :-)

See ya!

Jos

+----------------------------------------------------------------------+
|O   J.A. Horsmeier AND Software B.V.        phone : +31 10 4367100   O|
|O                  Westersingel 106/108     fax   : +31 10 4367110   O|
|O                  3015 LD  Rotterdam NL    e-mail: jos@and.nl       O|
|O--------------------------------------------------------------------O|
|O               I am a Hamburger (F. Zappa 1974)                     O|
+----------------------------------------------------------------------+

jfw@ksr.com (John F. Woods) (06/27/91)

diamond@jit533.swstokyo.dec.com (Norman Diamond) writes:
>In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
>>Hi there, I'll die if casting lvals is going to be illegal.
>>type* Thing;
>>((int)Thing)= Thing-Base+1;
>You'll die if you have to write
>  Thing = (type*) (Thing-Base+1);
>My heart bleeds for you.

Well, in fact, the second line isn't actually obligated to do what is
apparently desired, i.e. to copy the integer value bit-for-bit into the
pointer; the cast to a pointer is entitled to (if deemed desirable by the
compiler writer) change the representation to something that the hardware
would find more convenient.  The problem isn't really that J. Horsmeier
doesn't understand the subtleties of the language, it's that he doesn't
understand the fairly gross problem of portability.

To accomplish exactly what this person thinks is desired requires a union,
but of course that course is still fraught with peril, because the thing being
done is non-portable.

The bulk programming community seems to have gone from undergraduate VAX
programmers who just don't understand portability issues to geeky 8086
programmers who actively misunderstand portability; thank goodness Intel
is trying to exterminate all future microprocessor architectures in favor of
their washing-machine controller, or the next generation of programmers
might be completely useless!	:-)

mcdaniel@adi.com (Tim McDaniel) (06/27/91)

Oh, dear.  I had thought this horse had fossilized by now.

In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P.
Houghton) writes:

   This'll do it, too:

           thing += (int *)1;

   (see ANSI X3.159-1989, sec. 3.3.16.2, p. 55, ll. 20-21, and
   footnote 51 at the bottom of p. 51, for proof...)

In the ANSI-published version, footnote 51 is at the bottom of page
54, and deals with "the asymmetric appearance of these constraints
with respect to type qualifiers" in simple assignment, which means
"=".  It is therefore entirely irrelevant.  Page 51 has no footnotes.
Perhaps footnote 46 on page 48 was meant?  It deals with pointer
arithmetic, but is careful to specify "*integral* expression added to
or subtracted from the converted pointer" (emphasis mine).

The above-referenced p. 55, ll. 20-21 does say, under "Semantics" of
"Compound Assignment":

   A *compound* *assignment* of the form E1 *op*= E2 differs from the
   simple assignment expression E1 = E1 *op* (E2) only in that the
   lvalue E1 is evaluated only once.

However, the "Constraints" six lines up read:

   For the operators += and -= only, either the left operand shall be
   a pointer to an object type and the right shall have integral type,
   or the left operand shall have qualified or unqualified arithmetic
   type and the right shall have arithmetic type.

"(int *) 1" does not have integral type; it has pointer type.  Pointer
types and integral types are clearly distinguished in section 3.1.2.5,
"Types".

Section 3.3.6, "Additive Operators" (p. 47), (which applies due to the
"Semantics" section quoted above) has the constraint

   For addition, either both operand shall have arithmetic type, or
   one operand shall be a pointer to an object type and the other
   shall have integral type.

In section 3.3.4, "Cast Operators", in "Semantics",

   An arbitrary integer may be converted to a pointer.  The result is
   implementation-defined. \footnote{45. The mapping functions for
   converting a pointer to an integer or an integer to a pointer are
   intended to be consistent with the addressing structure of the
   execution environment.}

In short: bullshit.

				--Tim
				  "More accurately, it's fossilized
                                   horseshit."

--
  "Of course he has a knife; he always has a knife.  We all have knives.
  It's 1183 and we're barbarians." -- Eleanor of Aquitaine, "A Lion in Winter"
Tim McDaniel                 Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcdaniel@adi.com                UUCP: {uunet,sharkey}!amara!mcdaniel

burley@pogo.gnu.ai.mit.edu (Craig Burley) (06/27/91)

In article <998@baby.and.nl> jos@and.nl (J. Horsmeier) writes:

   It's my own choice.

Create your own language to make your own choices.  But don't try and claim
ANSI C is "wrong" or failed simply because you can't express something that
is meaningless or has a variety of meanings to different people.  C already
had enough baggage like that before ANSI got ahold of it.  No reason to add
anything new.

   I don't want any committee to forbid things like that 
   in any language.

Then don't use any languages standardized by any committees.  Like I said,
create your own language.  I've done it when it was appropriate to the task
at hand.

   A language is supposed to be a tool to express yourself, 
   the way you want and like to do so :-)

Wrong.  Take a bunch of cans of paint, reach your hands into arbitrary cans,
splatter paint on a canvas or wall, and you have just expressed yourself the
way you want -- but nobody is likely to understand what you are trying to
express.  Use a language of expression, whether abstract, symbolic, formal,
whatever, and do it well, and others will be able to understand it.  That is
the purpose of language.  If you want to do whatever you feel like as far
as "expressing yourself" in a computer language, like I said, write your own,
or at least use assembler (or, better yet, machine code the stuff directly).
But if you want others to be able to understand what you are writing, then
use the language, and learn to use it properly.

   Restricting syntactic and/or semantic
   richness of a language, just to avoid potential abuse by some zomby woofs
   from outer space is bad practice IMHO :-)

I agree, but that's not the case with disallowing

    ((int) thing)++;

and suchlike.  The ONLY "proper" interpretation of the above construct, given
what casts are in C, would be the following:

    Get the value of "thing".
    Convert that value (a temporary in a register, basically) to type "int".
    Increment that temporary.

But you seem to want it to mean something different, like:

    Get the value of "thing".
    Convert that value to type "int".
    Increment the result.
    Convert the result back to the type of "thing".
    Write the result back to "thing".

Or:

    Pretend "thing" really is an integer, and increment that.

These two things can have different results, and certainly they have results
different from the first definition, which does nothing.

Because lots of compilers allow this without warning (failings in those
compilers, perhaps), you can get away with the construct and write nonportable
and even incorrect code.  You might even discover that a compiler did something
unexpected with your code.  But these compilers can interpret your construct
however they wish, and only if they specifically describe what they do in their
documentation can you legitimately complain about their implementation (if it
is different from their description).

So please stop complaining about ANSI C as if it is restricting something
that should work the way you want, because:

1.  ANSI C did not restrict it, the restriction was always there in the
    language even if not in all compilers that implemented the language, as
    many others have mentioned.

2.  The whole point of ANSI C was to create a standard language based on a
    variety of dialects called "C" that somehow managed to satisfy a variety
    of criteria, primarily the portability of conforming programs to a wide
    variety of architectures and the ease of conversion from the various
    old dialects to the new standard language.  I believe it is reasonable to
    state that none of the individual criteria were satisfied 100%, but that
    the degree of satisfaction is higher for the criteria they deemed more
    important (at least for the most part).  It certainly is true that no
    language definition could have satisfied all the criteria 100%.

3.  The construct you show can be interpreted in a variety of ways by various
    experienced C programmers, as I illustrated above, and one of those
    interpretations is thoroughly nonportable, another is entirely out of the
    mold of C (the idea of storing a compiler-generated temporary back into
    its source location, without explicitly specifying an lvalue for the
    destination, does not exist in C, to my knowledge), and the other (the one
    I claim is most natural) is completely useless.

4.  There are better (more portable, more readable) ways to do what you want.
    (By "more readable" I do NOT mean "expressed in fewer characters", but
    "expressed within a subset of the language understood by a greater number
    of people compared to using a specific but rarely used construct".  For
    example, the phrase "Avoid making things more obscure than necessary" is
    more readable, despite being longer, than "Eschew obfuscation", even though
    the latter is funnier (once you look up the words) and, to the minority
    with a large enough vocabulary, more to the point.)

ANSI C has some dumb things about it (trigraphs spring immediately to mind...
OUCH! :-), but disallowing this construct is NOT one of them.
--

James Craig Burley, Software Craftsperson    burley@gnu.ai.mit.edu

gwyn@smoke.brl.mil (Doug Gwyn) (06/28/91)

In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes:
>	thing += (int *)1;

No, this doesn't work.

gwyn@smoke.brl.mil (Doug Gwyn) (06/28/91)

In article <4247@ksr.com> jfw@ksr.com (John F. Woods) writes:
>To accomplish exactly what this person thinks is desired requires a union,

I don't know exactly what that person thinks, if anything, but certainly a
union would not solve anything.  It would make things much worse in the
case of an implementation that represents different pointer types
differently.

The simple solution is to use a char* or void* as a "generic pointer" and
deal with the address arithmetic oneself.  This is really quite simple and
doesn't need to be hashed over in this (C standards) newsgroup.  It is not
a standards issue.

bhoughto@pima.intel.com (Blair P. Houghton) (06/28/91)

In article <16560@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes:
>>	thing += (int *)1;
>
>No, this doesn't work.

Not as a line of conforming code, no.

And yes, I did have a good (~3hr) nap.

				--Blair
				  "Makes one HELL of an alligator
				   repellent, though..."

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/28/91)

In article <998@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
>And I won't die either ...

Glad to hear it.

>I don't want to make a thread out of this, but I won't change my opinion
>about the `you get what you deserve' philosophy. 
>I like it, if I deserve non-portability, I want to get non-portability. 

OK, you asked for non-portability, you got non-portability, and you say
you wanted to get non-portability.  So why are you complaining here?
Your code works on your old compiler, and either it won't port to your
new ANSI-conformant compiler or else it will port with a diagnostic
message.  You got your non-portability.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/28/91)

In article <4247@ksr.com> jfw@ksr.com (John F. Woods) writes:
>diamond@jit533.swstokyo.dec.com (Norman Diamond) writes:
>>In article <992@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
>>>Hi there, I'll die if casting lvals is going to be illegal.
>>>type* Thing;
>>>((int)Thing)= Thing-Base+1;
>>You'll die if you have to write
>>  Thing = (type*) (Thing-Base+1);
>>My heart bleeds for you.
>
>Well, in fact, the second line isn't actually obligated to do what is
>apparently desired, i.e. to copy the integer value bit-for-bit into the
>pointer;

Yeah, well neither is the first line.  The first line intuitively should
not copy anything at all into the pointer, and legally can erase his hard
disk after issuing a diagnostic.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

jos@and.nl (J. Horsmeier) (06/28/91)

In article <BURLEY.91Jun27120009@pogo.gnu.ai.mit.edu> burley@pogo.gnu.ai.mit.edu (Craig Burley) writes:
>Create your own language to make your own choices.  But don't try and claim
>ANSI C is "wrong" or failed simply because you can't express something that
>is meaningless or has a variety of meanings to different people.  C already
>had enough baggage like that before ANSI got ahold of it.  No reason to add
>anything new.

I don't claim ANSI C is wrong, I was simply replying to a 'call to revolt',
'cause (I repeat myself), I like the philosophy: `You get what you deserve',
and given the hypothetical assumption that ANSI C was `going to forbid lvalue
casts' (read the original posting), I responded, that's all :-)

>   I don't want any committee to forbid things like that 
>   in any language.
>
>Then don't use any languages standardized by any committees.  Like I said,
>create your own language.  I've done it when it was appropriate to the task
>at hand.
>

Why should any committee forbid, non-portable, non-clearly-defined tricks etc.
offered by any language. Ripping these things out of a language is not doing
any good to that language. I *do* like the idea of commitment to a standard as
long as this standard simply enumerates all these non-portability pitfalls and
still allows one to use these hacks. Sometimes these things come in handy on
particular hardware environments, as long as you *know* and *realize* that
you're hacking close to the edge.

>   A language is supposed to be a tool to express yourself, 
>   the way you want and like to do so :-)
>
>Wrong.  Take a bunch of cans of paint, reach your hands into arbitrary cans,
>splatter paint on a canvas or wall, and you have just expressed yourself the
>way you want -- but nobody is likely to understand what you are trying to
[...]

No, as long as we are using the same tool (language), we can understand each
other. If both parties conform to the rules of the tool, they can communicate
the way they want. Even when a sentence contains syntactic or semantic errors,
people are capable of understanding each other. (This sentence contains two
errors).

>
>    ((int) thing)++;
>
>and suchlike.  The ONLY "proper" interpretation of the above construct, given
>what casts are in C, would be the following:
>
>    Get the value of "thing".
>    Convert that value (a temporary in a register, basically) to type "int".
>    Increment that temporary.
>
>But you seem to want it to mean something different, like:
>
>    Get the value of "thing".
>    Convert that value to type "int".
>    Increment the result.
>    Convert the result back to the type of "thing".
>    Write the result back to "thing".
[...]

Yep, that's exactly what I want (only with the stuff I'm currently working on).
I want an integer value plugged into the memory locations, previously containing
a pointer value. I know what I'm doing, I know it's not portable, I know about
different pointer sizes, I know it's not ethical,  etc. etc. etc. :-)
I know it can be done `the neat way', but all I want is a quick hack to do
the job, and I love it if a language gives me the opportunity to do so.
The stuff I'm working on now is not supposed to be portable, it's a dead end
anyhow, they just want the beast up and running for about six more months,
afterwards they let it die peacefully, so why bother about standards? 

>
>So please stop complaining about ANSI C as if it is restricting something
[...]

I'm not complaining about ANSI C. I like it when committees try to make
things explicit and `clear'. It can be a great help. Hidden language `features'
are a mess: define and elucidate them, but don't forbid them (which was the
original assumption). Label them as dangerous, bad practice or whatever and
clarify to the zomby woofs who still want to use them, that they're naughty boys
and girls =8^)

>
>ANSI C has some dumb things about it (trigraphs spring immediately to mind...
>OUCH! :-), but disallowing this construct is NOT one of them.

Who wants trigraphs anyway?

>James Craig Burley, Software Craftsperson    burley@gnu.ai.mit.edu

And please, let's not make a thread out of this, it's not worth the trouble.

See ya,

Jos


+----------------------------------------------------------------------+
|O   J.A. Horsmeier AND Software B.V.        phone : +31 10 4367100   O|
|O                  Westersingel 106/108     fax   : +31 10 4367110   O|
|O                  3015 LD  Rotterdam NL    e-mail: jos@and.nl       O|
|O--------------------------------------------------------------------O|
|O               I am a Hamburger (F. Zappa 1974)                     O|
+----------------------------------------------------------------------+

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/28/91)

In article <998@baby.and.nl>, jos@and.nl (J. Horsmeier) writes:
> And I won't die either ... but, currently I am working on an interface
> between *very* old C code and loads of FORTRAN stuff and I want to finish
> this project asap. To plough through all this f*ckin' code makes my
> mind go nuts, and invites one to fiddle/diddle these dirty tricks.

The ANSI committee has done *nothing* to stop you.

> I know it's all *absolutely* non-portable, it's dirty and should not be done,
> but I don't care in this particular case, I just want the thing up and running
> on just one type of machine, and these kinda tricks allow me to hack things
> together. 

The ANSI committee has done *nothing* to stop you.

What's really tragic about this, of course, is that the examples I've
seen so far were all things that could have been written portably in the
first place.

> I like it, if I deserve non-portability, I want to get non-portability. 
> It's my own choice. I don't want any committee to forbid things like that 
> in any language.

The ANSI committee has done *nothing* to stop you.
We're talking here about a feature which was always illegal according
to K&R1, but some compilers let you do it anyway.  So it wasn't portable.
We're talking about a feature which is not explicitly permitted by ANSI.
Has the ANSI committee *forbidden* any vendor to implement L-value casts?
*NO*!  Any vendor that wants to can implement L-value casts.  (I keep
trying to write that as "L-value costs".  Too apt.)  And then your program
can use them.  And it won't be portable.

In short, nothing has changed.

Remember, all that a standard does is say to a programmer "this is all
that you can rely on" and to a vendor "this is all you are obliged to
provide".  Standards don't, and can't, say to programmers "this is
all that you are allowed to use in any implementation" or to a vendor
"you may not provide more than this".  Don't accuse ANSI of forbidding
an unnecessary extension when all they did was refrain from requiring it!
-- 
I agree with Jim Giles about many of the deficiencies of present UNIX.

gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)

In article <4909@inews.intel.com> bhoughto@pima.intel.com (Blair P. Houghton) writes:
-In article <16560@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
->In article <4880@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes:
->>	thing += (int *)1;
->No, this doesn't work.
-Not as a line of conforming code, no.

It requires a diagnostic!!

-And yes, I did have a good (~3hr) nap.

Try a ~3yr nap.

sef@kithrup.COM (Sean Eric Fagan) (06/29/91)

I've got a bone to pick with X3J11, as well!  I had some code that worked
*fine* with my *K&R* compiler, but doesn't work with the ANSI compiler I
got.

The following *used* to work, but now doesn't!  I can't understand *how*
ANSI could even *begin* to define a language that *breaks* existing code!

	int foo(a, b) int a, b; {
		int tmp;
		/* some stuff */
		tmp = a*b;
	}

	main() {
		printf ("%d\n", foo(10, 20));
	}

I think we should all start a letter-writing campaign to protest how X3J11
*broke* C!

----
Editor's note:  the posted example is true, only the code has been
simplified to protect the innocent.  A certain version of Microsoft C for
Xenix '386 performed the multiply, and left the result in %eax.  A certain
version of GCC, seeing that the result was not returned, did not perform the
multiplication, therefore a random value was left in %eax.  The author of
the code is now serving maximum sentence in a COBOL shop.
----

-- 
Sean Eric Fagan  | "What *does* that 33 do?  I have no idea."
sef@kithrup.COM  |           -- Chris Torek
-----------------+              (torek@ee.lbl.gov)
Any opinions expressed are my own, and generally unpopular with others.

jos@and.nl (J. Horsmeier) (06/29/91)

In article <1991Jun28.040420.28730@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>In article <998@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
>>And I won't die either ...
>
>Glad to hear it.
>
[My silly stuff here ...]
>
>OK, you asked for non-portability, you got non-portability, and you say
>you wanted to get non-portability.  So why are you complaining here?
>Your code works on your old compiler, and either it won't port to your
>new ANSI-conformant compiler or else it will port with a diagnostic
>message.  You got your non-portability.
>--

Hi, please let's stop this silly discussion. Once and for all, I am *not*
complaining. Someone made the assumption of the ANSI C comittee forbidding
lvalue casts, and started a `call to revolt'. I replied, 'cause I liked the
subject. Ripping non-portable `features' out of a language is not doing any
good to that language. Warning people and making them aware of these non-
portable, dirty ga-ga's *is* doing some good to a language (like X3J11 does). 
But, if (and only if) portability is not a concern (like in my current
situation, I hope it'll change soon), why not stick ints into pointers with
a quick hack? Who cares? I know, char p; *((double*)&p)= 1.2345; could, and
probably will, kill your program. I know, I know, it's all ever so simple. 
I know of hundreds of different situations that are *not* portable or just
made possible by a flaw in the compiler, or have only rights to exist on 
zomby machines. And most of the time I don't use them!
But, for all sake, don't amputate them from a language (which was the original
assumption). Just advice people not to use them, and if they still want to:

		They get what they deserve!

Good for them. On the other hand, if you know what you're doing, 
who is entitled to forbid you from doing so? But anyhow, this became a 
thread already, let's stop it and talk about nicer things. 
This is moving from nowhere into la la land.

See ya! 8^)

Jos


+----------------------------------------------------------------------+
|O   J.A. Horsmeier AND Software B.V.        phone : +31 10 4367100   O|
|O                  Westersingel 106/108     fax   : +31 10 4367110   O|
|O                  3015 LD  Rotterdam NL    e-mail: jos@and.nl       O|
|O--------------------------------------------------------------------O|
|O while (1) *((int*)rand())= rand(); /* Why does it a core dump? */  O|
+----------------------------------------------------------------------+

jos@and.nl (J. Horsmeier) (06/29/91)

In article <1991Jun28.220128.22032@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>I've got a bone to pick with X3J11, as well!  I had some code that worked

[Yuck code deleted ...]

>
>I think we should all start a letter-writing campaign to protest how X3J11
>*broke* C!
>----
>Editor's note:  the posted example is true, only the code has been
[...]
>multiplication, therefore a random value was left in %eax.  The author of
>the code is now serving maximum sentence in a COBOL shop.
                                               ^^^^^

Try OBJECT-ORIENTED-COBOL, Like C++ they've called it:


                       ADD ONE TO COBOL GIVING COBOL


+----------------------------------------------------------------------+
|O   J.A. Horsmeier AND Software B.V.        phone : +31 10 4367100   O|
|O                  Westersingel 106/108     fax   : +31 10 4367110   O|
|O                  3015 LD  Rotterdam NL    e-mail: jos@and.nl       O|
|O--------------------------------------------------------------------O|
|O    MOVE CORRESPONDING SH*T TO TOILET BEFORE FLUSHING ONE LINE      O|
+----------------------------------------------------------------------+

gwyn@smoke.brl.mil (Doug Gwyn) (06/30/91)

In article <1015@baby.and.nl> jos@and.nl (J. Horsmeier) writes:
>This is moving from nowhere into la la land.

It started in la-la land.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/30/91)

In article <1015@baby.and.nl>, jos@and.nl (J. Horsmeier) writes:
> Hi, please let's stop this silly discussion.
> Once and for all, I am *not* complaining.
                    ^^^^^^^^^^^^^^^^^^^^^^

> Ripping non-portable `features' out of a language is not doing any
> good to that language.  ...
> But, for all sake, don't amputate them from a language
> (which was the original assumption).

If this isn't a complaint, it will do until the real thing comes along.
The thing which some posters seem to have difficulty grasping is that
X3J11 DID NOT RIP L-VALUE CASTS OUT OF THE LANGUAGE.  You might as well
complain that they removed the `max' and `min' operators from the
language!  Fact:  there were a couple of compilers around that provided
infix operators /\ and \/.  I _loved_ those operators; even fixed one of
the compiler so they worked.  That was a non-portable feature in
*precisely* the same sense as L-value casts.  We're not talking here
about an operation which wasn't well defined (like right shift of signed
integers, or the rules for combining signed and unsigned), we're talking
about features which, although _some_ compilers had them, were NEVER
part of "Classic C".

I wish that /\ and \/ were in ANSI C, but I don't whine about X3J11
"ripping them out of the language", and although it is far less trivial
to reorganise code to do without /\ and \/ than to do without L-value
casts (which don't even let you abbreviate by more than a couple of
characters), I don't accuse X3J11 of "amputating" the wings on that pig.

-- 
I agree with Jim Giles about many of the deficiencies of present UNIX.