[net.lang.c] Casting a postdecrement operand

lwh@romp.UUCP (lwh) (05/23/86)

My version of pcc on the IBM RT PC allows the following expression:


		struct abc { char d[500]; };
		struct cba { char e[200]; };
		struct cba *cbap;

		((struct abc *)cbap)++;


to increment cbap by 500. It appears that the ANSI standard doesn't say
anything about the legality of this syntax.  

Does anyone have any experience or opinions on this subject?


Larry Henson
{ihnp4 | seismo | gatech}!ut-sally!im4u!esc-bb!romp!lwh

The standard disclaimer: No one , not even me, is responsible.

greg@utcsri.UUCP (Gregory Smith) (05/26/86)

In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes:
>My version of pcc on the IBM RT PC allows the following expression:
>
>		struct abc { char d[500]; };
>		struct cba { char e[200]; };
>		struct cba *cbap;
>
>		((struct abc *)cbap)++;
>
>
>to increment cbap by 500. It appears that the ANSI standard doesn't say
>anything about the legality of this syntax.  
>
First, a technical point: There is nothing wrong with the `syntax', which
is identical to the syntax of
		(( struct foobar * ) pp )++;
The *semantics*, though, are a different question. You are saying
'Treat cbap as a pointer to a (struct abc); increment that pointer'.
The compiler dutifully adds 500. ( You asked for it, you got it... )
This is perfectly legal, but lint might well want to prod you about it...
Since you are explicitly casting the pointer, though, it should be plain
that you have good reasons to do so.

-- 
"We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg

jss@ulysses.UUCP (Jerry Schwarz) (05/28/86)

In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes:
>My version of pcc on the IBM RT PC allows the following expression:
>
>		((struct abc *)cbap)++;
>
>
>to increment cbap by 500. It appears that the ANSI standard doesn't say
>anything about the legality of this syntax.  

"++" requires an lvalue. A cast produces a value but not an lvalue,
so this is not legal in ANSI (or in K&R ) C. 

Jerry Schwarz
Bell Labs, MH

Comment:

Many C compilers (especially those derived from pcc) have a tendency
to "extend C by convenience". That is, they have an algorithm that
generates code on correct C programs. They give an error message only
when that algorithmn runs into trouble.  On some illegal programs the
algorithm doesn't run into any problems and so they generate code
anyway.

In this case, I guess that the compiler does not keep track of
whether an expression is an lvalue in the "syntax" rather it detects
it in the "semantics".    In some circumstances it implements a cast
applied to an "identifier"  by changing the data structure to pretend
that the "name" has the modified type.  The combination of these two
results in the behavior you observe.

rgh@inmet.UUCP (05/31/86)

> My version of pcc on the IBM RT PC allows the following expression:
>
>	struct abc { char d[500]; };
>	struct cba { char e[200]; };
>	struct cba *cbap;
>
>	((struct abc *)cbap)++;
>
> to increment cbap by 500. It appears that the ANSI standard doesn't say
> anything about the legality of this syntax.  

This is covered in the draft Standard:  (1) a cast does not yield an
lvalue;  (2) the operand of post-inc must be an lvalue.  So the
construct is illegal.

Standard-conforming syntax using the same idea is

	#define LCAST(typeP, lvalue)       ( *( (typeP *) &lvalue ) )
	#define INC_BY_SIZEOF(ptr, typeD)  ( LCAST(typeD *, ptr)++ )

	INC_BY_SIZEOF(cbap, struct abc);

Semantically this works only so long as the type that  ptr  points to
has the same alignment requirement as  typeD ,
and (a more subtle point) as long as  typeP
has the same representation as  ptr .

    Randy Hudson  {ihnp4,cca!ima}!inmet!rgh

throopw@dg_rtp.UUCP (Wayne Throop) (06/01/86)

> greg@utcsri.UUCP (Gregory Smith)
>> lwh@romp.UUCP (lwh)

>>My version of pcc on the IBM RT PC allows the following expression:
>>                ((struct abc *)cbap)++;
>>to increment cbap by 500. It appears that the ANSI standard doesn't say
>>anything about the legality of this syntax.  

Well, no.  It says that the *syntax* is legal.  The *semantics* of such
an increment are explicitly outlawed.  A cast does *not* mean and
*never* *has* meant to "treat the bits as a new type".  It means
*convert* the bits to the new type, and this conversion is machine
dependant, and *never* results in an lvalue.

> First, a technical point: There is nothing wrong with the `syntax',

Right, right.

> The *semantics*, though, are a different question.

Yes, yes.

> You are saying
> 'Treat cbap as a pointer to a (struct abc); increment that pointer'.

No, no.

That may be what lwh *meant*, but that's not what he *said*.  What he
*said* was to increment a non-lvalue expression.  Just as meaningful as
saying "(i+j)++".  Which is to say, not very meaningful.

> The compiler dutifully adds 500. ( You asked for it, you got it... )

Well, *his* compiler dutifully adds an ammount large enough to reach the
next (struct abc), which on his machine happens to be 500.  Rephrasing,
there are two interesting issues here.  First, the fact that the
compiler allows a cast to be used as an lvalue is bogus in the first
place.  That compiler, quite simply, allowed an illegal operation.  In
the second place, performing the increment-by-1 operation on a (struct
abc *) is a machine-dependant operation, which on lwh's machine happens
to change the pointer's bit-pattern in such a way that, if that bit
pattern had been a twos-complement integer, we would have said it was
incremented by 500.  As I say, machine dependant to the max.

> This is perfectly legal, but lint might well want to prod you about it...

It is *not* legal, perfectly or imperfectly.  And lint *had* *better*
prod you about it.  (It does, by the way.  It says "illegal lhs of
assignment".)

> Since you are explicitly casting the pointer, though, it should be plain
> that you have good reasons to do so.

As may be.  But once you have cast the pointer, you cannot use the cast
expression as an lvalue.  K&R say this is illegal, Harbison and Steele
say this is illegal, and the ANSI draft says this is illegal.  I mean,
when the Father, the Son, and the Holy Ghost say it's illegal, I say it
is then, now, and evermore, *ILLEGAL*.
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

ron@brl-sem.ARPA (Ron Natalie <ron>) (06/01/86)

In article <1273@ulysses.UUCP>, jss@ulysses.UUCP (Jerry Schwarz) writes:
> In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes:
> >		((struct abc *)cbap)++;
> >to increment cbap by 500. It appears that the ANSI standard doesn't say
> >anything about the legality of this syntax.  
> 
> "++" requires an lvalue. A cast produces a value but not an lvalue,
> so this is not legal in ANSI (or in K&R ) C. 
I find this disgusting but
		( *((struct abc **)&cbap) )++;
would work.

INEWS SUCKS
INEWS SUCKS
INEWS SUCKS
INEWS SUCKS

chris@umcp-cs.UUCP (Chris Torek) (06/01/86)

Incidentally, if you really *do* want to take a pointer `p' to
type `x', but treat it as a pointer to type `y', the construct

	*(y **)&p

works (as long as `p' is addressable).  Thus

	((struct abc *)cbap)++;

is not legal, but

	(*(struct abc **)&cbap)++;

is (again, if cbap is addressable).  What it means is machine
dependent!
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

greg@utcsri.UUCP (Gregory Smith) (06/01/86)

In article <378@dg_rtp.UUCP> throopw@dg_rtp.UUCP (Wayne Throop) writes:
>there are two interesting issues here.  First, the fact that the
>compiler allows a cast to be used as an lvalue is bogus in the first
>place. That compiler, quite simply, allowed an illegal operation.
[me:]
>> This is perfectly legal, but lint might well want to prod you about it...
>
>It is *not* legal, perfectly or imperfectly.  And lint *had* *better*
>prod you about it.  (It does, by the way.  It says "illegal lhs of
>assignment".)

>...once you have cast the pointer, you cannot use the cast
>expression as an lvalue.  K&R say this is illegal, Harbison and Steele
>say this is illegal, and the ANSI draft says this is illegal.  I mean,
>when the Father, the Son, and the Holy Ghost say it's illegal, I say it
>is then, now, and evermore, *ILLEGAL*.
>-- 
>Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

I stand corrected. I couldn't find anything explicitly forbidding or
allowing this in K&R, ( I still can't ) so I gave that compiler the
benefit of the doubt, without trying it here. Reasonable semantics
could be defined for the operation, but I don't know how useful it is.

-- 
"We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg

david@sun.uucp (David DiGiacomo) (06/04/86)

In article <1764@umcp-cs.UUCP> chris@maryland.UUCP (Chris Torek) writes:
>Incidentally, if you really *do* want to take a pointer `p' to
>type `x', but treat it as a pointer to type `y', the construct
>
>	*(y **)&p
>
>works (as long as `p' is addressable).  Thus
>
>	((struct abc *)cbap)++;
>
>is not legal, but
>
>	(*(struct abc **)&cbap)++;
>
>is (again, if cbap is addressable).  What it means is machine
>dependent!

This is disgusting... why not use

	cbap = (struct cba *) ((caddr_t) cbap + sizeof(struct abc));

?

-- 
David DiGiacomo  {decvax, ihnp4, ucbvax}!sun!david  david@sun.arpa
Sun Microsystems, Mt. View, CA  (415) 960-7495

throopw@dg_rtp.UUCP (Wayne Throop) (06/07/86)

> greg@utcsri.UUCP (Gregory Smith)

> I stand corrected. I couldn't find anything explicitly forbidding or
> allowing this in K&R, ( I still can't ) so I gave that compiler the
> benefit of the doubt, without trying it here.

For those interested, here are the places that make

        ((T *)P)++

illegal.  First, in K&R, two places.  In the reference section, 7.2,
unary operators:

    An expression preceeded by the parenthesized name of a data type
    causes conversion of the value of the expression to the named type.
    This construction is called a cast.

Note that the *value* is *converted*.  K&R are careful to call lvalues
lvalues, and the note that a cast works on the value of the expression
is noteworthy.  Note also that this value is *converted*.  It is *not*
"taken as a new type".  As an interesting digression, this is probably
the source of much confusion over casts, since many think that they are
conversion sometimes, and "look at T1-type bits through T2-colored
glasses" other times.  This is *not* the case... a cast is *always* a
conversion.  In C there are only two ways to take T1-typed-bits as if
they were T2-typed-bits.  Put the bits into a union of T1 and T2, or
cast a pointer to them.  (Well, they are the only two ways I could think
of, anyhow.)

Then note, in 5, objects and lvalues:

    The discussion of each operator below indicates whether it expects
    lvalue operands and whether it yields an lvalue.

Casts do not state that they yield lvalues, and postincrement expects
one.  So the combination is semantically illegal according to K&R.

In Harbison and Steele, things are simpler.  In chapter seven, they list
the operators that yield lvalues, which are

        e1[e2], (e) {if e is lvalue}, e.name {if e is lvalue}
        e->name, and *e

and conclude the paragraph, saying

    No other form of expression can produce an lvalue.

And in the same section, they state that postincrement requires an
lvalue.

The ANSI draft says in section 3.4

    Note: A cast does not return an lvalue.

As I say, Father, Son and Holy Ghost all agree on this point.

> Reasonable semantics
> could be defined for the operation, but I don't know how useful it is.

On first glance, it *does* seem reasonable.  But upon more detailed
thought, it turns out not to be the case.  The whole point is that
reasonable semantics *cannot* be defined for the operation in a machine
independant way.  The reasoning of the ANSI folks is spelled out in the
May '86 Dr. Dobb's Journal on page 20 in a section titled "Beating Dead
Horses" if you want to look it up, but the short form of this argument
is fairly simple.  You say that

        ((T *)P)++

can be given reasonable semantics.  This either means that pointers are
drastically different from other types (in ways that are inconvenient
and/or arbitrary), or this construction can also be given reasonable
semantics:

        ((T)L)++

Filling in something concrete for the type and the lvalue, and assuming
that "i" is an integer lvalue:

        ((float)i)++

Do you really want to contend that this is reasonable?  If so, what does
it mean?  Either the semantics of C must be made very irregular and
strange to allow ((T *)P)++, or the notion of any cast being an lvalue
must be discarded.  In addition to complexity and irregularity, possible
semantics of casts of lvalues *being* lvalues are extremely machine
dependant (in particular (in current implementations that allow them),
the pointer cases depend on the pointer format for all pointer types
being identical).  This is *not* something that is "reasonable" to add
to an allegedly machine independant language.
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

throopw@dg_rtp.UUCP (Wayne Throop) (06/08/86)

> david@sun.UUCP (David DiGiacomo)
>> chris@maryland.UUCP (Chris Torek)

>>      ((struct abc *)cbap)++;
>>is not legal, but
>>      (*(struct abc **)&cbap)++;
>>is (again, if cbap is addressable).  What it means is machine
>>dependent!

> This is disgusting... why not use
>       cbap = (struct cba *) ((caddr_t) cbap + sizeof(struct abc));

Because the latter construct mentions "cbap" twice.  Thus, if this type
of expression were embedded in a macro, "cbap" had better not contain
side effects.  Also, if "cbap" is difficult or complicated (you know,
something like (*f1(a[s1][e1+e2],f2())) or worse), then expanding it
twice might be undesirable even if it *were* side effect free.

In short, it is indeed *useful* to do such things, just as things like
(i += 2) are useful... but nobody has found a way to give the language
sensible, consistent semantics if such a thing is allowed.

Now, I know what you're thinking.  You're thinking, ok, so why not

    cbap += (sizeof(struct abc) / sizeof(struct cba));

(assuming that the division has no remainder, of course, as might often
be the case, or as may be arranged to be the case.)  Well, because this
isn't a post-increment construct, and that is what the whole thing
started out over... somebody noticed that the pcc allows a
post-increment on a cast of a pointer for some machines.

The moral is, it just isn't possible to avoid mentioning an instance
twice in all possible perverse cases.  Sad but true.  If it is really
important to mention an instance only once, and then get at that
instance many times, a binding-by-reference would work:

    {   T *p = &reference_of_type_T_that_i_only_want_to_mention_once;
        ... *p ... *p ... *p ...
    }

Now you can use the object that the complicated reference mentions as an
lvalue many times, yet only evaluate it once.  Yes, you are right... it
*isn't* pretty.  But sometimes a Programmer's gotta do what a
Programmer's gotta do, a-yuh.

--
"Now men, we've got uh new villuge ta raid.
 I want ya ta kill all the men,
 round up all the livestock,
 an' ravage all the wimmun.

 An' fer *God*'s *sake* get it *right* this time!"

                Rich Little as John Wayne, in the role of Ghengis Khan.
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

rgh%inmet.uucp@BRL.Arpa (06/10/86)

Return-Path: <info-c-request@BRL.ARPA>
Redistributed: Xerox-Info-C^.x@XEROX.ARPA
Received: from BRL-AOS.ARPA by Xerox.COM ; 02 JUN 86 16:42:06 PDT
Received: from brl-smoke.arpa by AOS.BRL.ARPA id a015894; 2 Jun 86 17:10 EDT
Received: from USENET by SMOKE.BRL.ARPA id a005080; 2 Jun 86 16:42 EDT
Newsgroups: net.lang.c
Message-ID: <5000043@inmet>
Nf-ID: #R:romp.UUCP:114:inmet:5000043:000:919
Nf-From: inmet.UUCP!rgh    May 31 14:55:00 1986


> My version of pcc on the IBM RT PC allows the following expression:
>
>	struct abc { char d[500]; };
>	struct cba { char e[200]; };
>	struct cba *cbap;
>
>	((struct abc *)cbap)++;
>
> to increment cbap by 500. It appears that the ANSI standard doesn't say
> anything about the legality of this syntax.  

This is covered in the draft Standard:  (1) a cast does not yield an
lvalue;  (2) the operand of post-inc must be an lvalue.  So the
construct is illegal.

Standard-conforming syntax using the same idea is

	#define LCAST(typeP, lvalue)       ( *( (typeP *) &lvalue ) )
	#define INC_BY_SIZEOF(ptr, typeD)  ( LCAST(typeD *, ptr)++ )

	INC_BY_SIZEOF(cbap, struct abc);

Semantically this works only so long as the type that  ptr  points to
has the same alignment requirement as  typeD ,
and (a more subtle point) as long as  typeP
has the same representation as  ptr .

    Randy Hudson  {ihnp4,cca!ima}!inmet!rgh

davidsen@steinmetz.UUCP (Davidsen) (06/12/86)

In article <1273@ulysses.UUCP> jss@ulysses.UUCP writes:
>In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes:
>>My version of pcc on the IBM RT PC allows the following expression:
>>
>>		((struct abc *)cbap)++;
>>
>>
>>to increment cbap by 500. It appears that the ANSI standard doesn't say
>>anything about the legality of this syntax.  
>
>"++" requires an lvalue. A cast produces a value but not an lvalue,
>so this is not legal in ANSI (or in K&R ) C. 
>
>Jerry Schwarz
>Bell Labs, MH

The variable 'cbap' is a pointer. The cast '(struct abc *)' is a
pointer cast. I can use '((struct abc *)cbap)' with indirects and
subscripts and anywhere that I can use an Lvalue, so I really believe
that the expression is legal.

Now, as to being *portable*. There is some language in the X3J11
proposed standard about possible loss of information and
non-portability when pointers are cast. This is why the 'void *' type
was introduced (in part) to have a pointer which could hold any valid
data address. However, there is no guarantee that when the address of
one data type, however obtaining, is cast to a pointer to another data
type that the result will be valid.

If I recall correctly the term in use in X3J11 for stuff was "valid but
non-portable". Sorry I can't remember for sure who said it. I hope this
clarifies the question somewhat (it does in my mind, anyway).
-- 
	-bill davidsen

  ihnp4!seismo!rochester!steinmetz!--\
                                       \
                    unirot ------------->---> crdos1!davidsen
                                       /
         sixhub ---------------------/        (davidsen@ge-crd.ARPA)

"Stupidity, like virtue, is its own reward"

throopw@dg_rtp.UUCP (Wayne Throop) (06/14/86)

> davidsen@steinmetz.UUCP (Davidsen)

[discussing the illegal C expression ((struct abc *)cbap)++]

> The variable 'cbap' is a pointer.
        Correct.

> The cast '(struct abc *)' is a pointer cast.
        Correct.

> I can use '((struct abc *)cbap)' with indirects and subscripts
        Correct.

> and anywhere that I can use an Lvalue,
        "Non sequitur.  Your thinking is un-co-ordinated."

Wrong.  I say again, ****WRONG****.  The "lvaluehood" of an expression
is *NOT* *NOW*, and *HAS* *NEVER* *BEEN*, implied by the legality of the
use of that expression in pointer arithmetic and indirection.

You don't seem to know what an lvalue is, nor do you seem to know what
entities in C are lvalues.  An lvalue is an expression that can appear
as the left subexpression of an assignment operator.  Saying that a cast
is an lvalue is as nonsensical as saying that (a+b) is an lvalue, or
that (&x) is an lvalue.  Casts do *NOT* yeild lvalues.  They *DO* *NOT*
*NOW*, and they *NEVER* *HAVE*.  God willing they *NEVER* *WILL*.

I appologize for my vehemence, but this issue comes up over and over and
over and over and over and over and over and over and over.   And over.
I am using caps and stars to try to *GET* *YOUR* *ATTENTION*!!!!!
*HEY*!!!  *ANYBODY* *IN* *THERE*????  *CASTS* *NEVER* *YIELD*
*LVALUES*!!!!!!!!!!!!   *NEVER*!!!!!!!! ********* N E V E R *******!!!!
**N**O**T**  **E**V**E**R**!!!!!!!!!!!!

I have posted references in K&R and the ANSI draft standard that support
my position.  I have posted a reference to a recent Dr Dobbs where
the issue was discussed in endless boring detail.  Those that think
otherwise say things like this:

> so I really believe that the expression is legal.

Great.  And my aunt Martha believes pigs can fly.  She is wrong.  And so
are you.  My appologies if my prior postings simply didn't arive at your
site.  My appologies for any offense I may have given.  And in general,
profuse appology for my state of extreme annoyance and exasperation.
But, confound it, I am right about this, and you are wrong, and yet
people that hold this incorrect opinion keep posting and posting and
posting and posting.  It's a conspiracy, I tell you!  You're all out to
*GET* me!  But you won't... no, I won't *LET* you!  Get them *OFF* me,
get them **OFF**, spiders, can't you *SEE* them, they're crawling
all ****OVER**** me....

AAAAAAAUUUUUUUGGGGGGGHHHHHHH!!!!!!!!

--
Well, I feel a *little* better after the sedation.
But shouting *does* exhaust one so.

--
What's that?  You say you want the references again?  They were

  - K&R, sections 7.2 and 5 in the reference part.
  - Harbison and Steele, first few paragraphs of chapter 7.
  - ANSI draft standard, section 3.4.
  - Dr. Dobbs Journal, May 1986, page 20, under the heading
        "Beating Dead Horses"  (most appropriate!)
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

jss@ulysses.UUCP (Jerry Schwarz) (06/15/86)

> 
> The variable 'cbap' is a pointer. The cast '(struct abc *)' is a
> pointer cast. I can use '((struct abc *)cbap)' with indirects and
> subscripts and anywhere that I can use an Lvalue, so I really believe
> that the expression is legal.
> 	-bill davidsen

Being a pointer value is not the same as being an lvalue. The places
that require lvalues are left hand side of assignments, and operands
of the increment and decrement operations. In none of these locations
is '((struct abc*)cbap)' legal.

If p is an expression with a (data) pointer type then *p will
be an lvalue, so 
	++ *((struct abc**)&cbab) 
will modify cbab.

Jerry Schwarz
Bell Labs, MH

kenny@uiucdcsb.CS.UIUC.EDU (06/17/86)

/* Written 11:52 am  Jun 12, 1986 by davidsen@steinmetz.UUCP in uiucdcsb:net.lang.c */
>In article <1273@ulysses.UUCP> jss@ulysses.UUCP writes:
>>In article <114@romp.UUCP> lwh@romp.UUCP (lwh) writes:
>>>My version of pcc on the IBM RT PC allows the following expression:
>>>
>>>		((struct abc *)cbap)++;
>>>
>>>
>>>to increment cbap by 500. It appears that the ANSI standard doesn't say
>>>anything about the legality of this syntax.  
>>
>>"++" requires an lvalue. A cast produces a value but not an lvalue,
>>so this is not legal in ANSI (or in K&R ) C. 
>>
>>Jerry Schwarz
>>Bell Labs, MH
>
>The variable 'cbap' is a pointer. The cast '(struct abc *)' is a
>pointer cast. I can use '((struct abc *)cbap)' with indirects and
>subscripts and anywhere that I can use an Lvalue, so I really believe
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- NO!
>that the expression is legal.
>
>Now, as to being *portable*. There is some language in the X3J11
>proposed standard about possible loss of information and
>non-portability when pointers are cast. This is why the 'void *' type
>was introduced (in part) to have a pointer which could hold any valid
>data address. However, there is no guarantee that when the address of
>one data type, however obtaining, is cast to a pointer to another data
>type that the result will be valid.
>
>If I recall correctly the term in use in X3J11 for stuff was "valid but
>non-portable". Sorry I can't remember for sure who said it. I hope this
>clarifies the question somewhat (it does in my mind, anyway).
[ ... ]

/* End of text from uiucdcsb:net.lang.c */

No, no, no!  You can *dereference* ((struct abc *) cbap).  You can subscript
it, you can put a * in front of it, you can use it anywhere you can use a
pointer *rvalue*.  What you can't do is use it in any context requiring an
*lvalue*.  You can't ++ it, you can't -- it, you can't = (+=, -=, ...) into
it, and you can't put an & in front of it.  If you wanted to force
incrementation of cbap as a (struct abc *) and throw portability to the
winds, and you know that different types of pointer share the same
representation on your machine, you might try ++*((struct abc **) &cbap).
I wouldn't.

Now, class, three times slowly:  Casts are rvalues.  Casts are rvalues.
Casts are rvalues.

Kevin Kenny
University of Illinois at Urbana-Champaign
UUCP: {ihnp4,pur-ee,convex}!uiucdcs!kenny 
CSNET:	kenny@UIUC.CSNET
ARPA:	kenny@B.CS.UIUC.EDU	(kenny@UIUC.ARPA)

"Yes, understanding today's complex world is a bit like having bees live in
your head, but there they are."

davidsen@steinmetz.UUCP (Davidsen) (06/24/86)

In article <1295@ulysses.UUCP> jss@ulysses.UUCP (Jerry Schwarz) writes:
>> 
>> The variable 'cbap' is a pointer. The cast '(struct abc *)' is a
>> pointer cast. I can use '((struct abc *)cbap)' with indirects and
>> subscripts and anywhere that I can use an Lvalue, so I really believe
>> that the expression is legal.
>> 	-bill davidsen
>
>Being a pointer value is not the same as being an lvalue. The places
>that require lvalues are left hand side of assignments, and operands
>of the increment and decrement operations. In none of these locations
>is '((struct abc*)cbap)' legal.

>> subscripts and anywhere that I can use an Lvalue, so I really believe
					     ^^^^^^
A thousand pardons! I was thinking about Lvalues, and wrote Lvalue
where I meant "address value". The point I was making (trying to amke)
was that the result of the cast operation is legen *in* an Lvalue,
where a pointer would be, not that I thought it was an Lvalue as is.
  Example:
	*((float *) ptr) = 4.5; /* ptr is char * type */

The other question was the legality of a cast on increment, and rather
than read books and standards, I actually tried it, based on the theory
that what happened in most places is "current practice". So far I have
found 3 of seven compilers which compile code for
  ((float *) ptr)++; /* ptr type is char * */
so I make no claims one way or the other.

NOTE: I am not claiming that either of these is portable or useful, but
that's not the same thing as valid. Current practice is why enums are
done as integers rather than being truly a distinct data type. They
were added because the preprocessor ran out of symbol space as far as I
know.

Thanks to the people who pointed out the poor explanation in the
earlier posting. All were polite except one jerk who sent six screens
of flames and a ficticious .signature at the end. I hope this didn't
confuse anyone.
-- 
	-bill davidsen

  ihnp4!seismo!rochester!steinmetz!--\
                                       \
                    unirot ------------->---> crdos1!davidsen
                          chinet ------/
         sixhub ---------------------/        (davidsen@ge-crd.ARPA)

"Stupidity, like virtue, is its own reward"