[comp.lang.c] &&**

ridoux@irisa.fr (Olivier Ridoux) (09/06/90)

Hello,

I'd like to know about the portability of expressions of the form 
`` &^n*^n x '' (`` &*x '', `` &&**x '', `` &&&***x '', ...).

An expression of the form `` &&x '' seems to make no sense, since `` & '' 
requires a lvalue though it yields no lvalue.  So `` &&**x '' seems to be 
ruled out.

However, `` &*x '' and `` x '' have the same value though `` x '' may be a 
lvalue and `` &*x '' cannot if `` & '' is interpreted conservatively.  So 
expressions of the form `` &^n*^n x '' can be reduced to `` x '' through 
algebraic manipulation.  One can even consider that `` &^n*^n x '' has the 
lvalue-ness of `` x '' (in contrast with the conservative interpretation of 
`` & '').  The gcc compiler performs this algebraic simplification.

My question is: can a programmer expect that every C compiler will perform the
algebraic simplification of `` &^n*^nx '' to `` x '', and what will be the 
lvalue-ness of the expression ?

I thank you in advance,

Olivier Ridoux

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/07/90)

In article <1990Sep6.091605.15732@irisa.fr> ridoux@irisa.fr (Olivier Ridoux) writes:
  [ is &&&&&&******x portable? ]

No. Even if ******x has a meaning, its && does not.

  [ x is &*x, so x is &&&&&*****x by ``algebraic manipulation'' ]

No. You can reduce &*&*&*&*&*&*&*x to x, given x of a pointer type. But
you can't apply ``algebraic manipulation'' to meaningless expressions.

---Dan

datanguay@watmath.waterloo.edu (David Adrien Tanguay) (09/07/90)

In article <1990Sep6.091605.15732@irisa.fr> ridoux@irisa.fr (Olivier Ridoux) writes:
|I'd like to know about the portability of expressions of the form 
|`` &^n*^n x '' (`` &*x '', `` &&**x '', `` &&&***x '', ...).
|
|An expression of the form `` &&x '' seems to make no sense, since `` & '' 
|requires a lvalue though it yields no lvalue.  So `` &&**x '' seems to be 
|ruled out.

Also note that the "&&" sequences in the above expressions will lex as
"logical and" operators.
-- 
David Tanguay            Software Development Group, University of Waterloo

ridoux@irisa.fr (Olivier Ridoux) (09/07/90)

From article <1990Sep7.021321.18381@watmath.waterloo.edu>, by datanguay@watmath.waterloo.edu (David Adrien Tanguay):
> In article <1990Sep6.091605.15732@irisa.fr> ridoux@irisa.fr (Olivier Ridoux) writes:

> |`` &^n*^n x '' (`` &*x '', `` &&**x '', `` &&&***x '', ...).
> 
> Also note that the "&&" sequences in the above expressions will lex as
> "logical and" operators.

I apologize.  I should have fully parenthesized all the expressions.  Since I
was only dealing with operators `` & '' and `` * '' I thought it was
unambiguous.  `` && '' must not interfer in the game.

My question is not on the validity of the composition of the operator `` & ''.
It is rather "what is the rational of the cc and gcc compilers (sun4) that 
makes them accept the following program.  Can I expect that every C compiler
will have the same rational ?

My opinion is that the rational is based on the axiom: `` &(*(x)) = x ''.
Note that this axiom is not a consequence of the book (K&R).

main()
{
char c = 'c' ;
char * pc = &c ;
char ** ppc = &pc ;

char d = 'd' ;
char * pd = &d ;
char ** ppd = &pd ;

  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 1 */

  printf( "%c\n", *(*( &(&(*(*(ppd)))) )) );  /* 2 */

  &(&(*(*(ppc)))) = ppd ;
  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 3 */

}

1 (and 2) shows that the composition of `` & '' is interpreted by the compiler,
though the book says it is not valid because `` & '' requires a lvalue and
yields no lvalue.

3 shows that the expression `` &(&(*(*(ppc)))) '' is even an lvalue.  I think
it is because `` ppc '' is an lvalue.

Olivier Ridoux

rankin@eql.caltech.edu (Pat Rankin) (09/08/90)

In article <1990Sep7.080855.24070@irisa.fr>, ridoux@irisa.fr (Olivier Ridoux) writes...
[...]
>My question is not on the validity of the composition of the operator `` & ''.
>It is rather "what is the rational of the cc and gcc compilers (sun4) that 
>makes them accept the following program.  Can I expect that every C compiler
>will have the same rational ?

     VAXC (VMS) rejects it:
[...]
>  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 1 */
%CC-E-INVOPERAND, Invalid operand of a "& (address-of)" operator.

(Same error repeated for the other similar lines.  VAXC V3.1)

                Pat Rankin, rankin@eql.caltech.edu

throopw@sheol.UUCP (Wayne Throop) (09/10/90)

> From: ridoux@irisa.fr (Olivier Ridoux)
> "what is the rational of the cc and gcc compilers (sun4) that 
> makes them accept the following program.

Presumably, merely because they are buggy compilers.

> Can I expect that every C compiler will have the same rational ?

I certainly hope not.  It seems to me that about the only way that
allowing &(&(...)) makes any sense at all is as part of a larger
picture that supports the operation of essentially all "lvalue"
requiring operators on value arguments.  This larger context would
have to deal with rules for things like when, how, and for how long
"pseudo-objects" would be created so that lvalue-requiring semantics
could be meaningful.  It might improve the language in some ways.

I emphasize: "might".

Now, on the other hand, I ran this program through microsoft C,
feeling confident that it would be flagged as erronious.  To my
surprise and amazement, it ran just as Olivier describes.  No
slips, no drips, (and worst) no errors.

This is apparently a VERY common bug.  It shakes my faith in
the competence of C implementors.  Unless I'm missing something
quite major...???


(the program in question:)

main()
{
char c = 'c' ;
char * pc = &c ;
char ** ppc = &pc ;

char d = 'd' ;
char * pd = &d ;
char ** ppd = &pd ;

  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 1 */

  printf( "%c\n", *(*( &(&(*(*(ppd)))) )) );  /* 2 */

  &(&(*(*(ppc)))) = ppd ;
  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 3 */

}
--
Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org

scjones@thor.UUCP (Larry Jones) (09/10/90)

In article <0926@sheol.UUCP>, throopw@sheol.UUCP (Wayne Throop) writes:
> [ about compilers allowing "&(&(&(***x)))" ]
> This is apparently a VERY common bug.  It shakes my faith in
> the competence of C implementors.  Unless I'm missing something
> quite major...???

It's a very easy mistake to make.  Since both &* and *& are
essentially noops, most compilers will remove adjacent pairs
as part of the optimization of expression trees.  Since tree
rewriting is generally iterative, this results in all such
pairs being removed.  Semantic restrictions (like lvalueness)
are generally not tested until after rewriting, so bogus code
like this slips through.
----
Larry Jones                         UUCP: uunet!sdrc!thor!scjones
SDRC                                      scjones@thor.UUCP
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
Why can't I ever build character in a Miami condo or a casino somewhere?
-- Calvin

sa1z+@andrew.cmu.edu (Sudheer Apte) (09/11/90)

throopw@sheol.UUCP (Wayne Throop) writes:
> > From: ridoux@irisa.fr (Olivier Ridoux)
> > "what is the rational of the cc and gcc compilers (sun4) that 
> > makes them accept the following program...
> ...
> Now, on the other hand, I ran this program through microsoft C,
> feeling confident that it would be flagged as erronious.  To my
> surprise and amazement, it ran just as Olivier describes.  No
> slips, no drips, (and worst) no errors.
> 
> This is apparently a VERY common bug.  It shakes my faith in
> the competence of C implementors.  Unless I'm missing something
> quite major...???

You are quite correct.  GNU's gcc compiles it without a peep!
What is going on?  The standard seems quite clear about this,  but
I've never known gcc to misbehave before...

	Sudheer.
------------------
The program:

main()
{
char c = 'c' ;
char * pc = &c ;
char ** ppc = &pc ;

char d = 'd' ;
char * pd = &d ;
char ** ppd = &pd ;

  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 1 */
  printf( "%c\n", *(*( &(&(*(*(ppd)))) )) );  /* 2 */
  &(&(*(*(ppc)))) = ppd ;
  printf( "%c\n", *(*( &(&(*(*(ppc)))) )) );  /* 3 */

}



...{harvard, uunet}!andrew.cmu.edu!sa1z
sa1z%andrew@CMCCVB.BITNET

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/11/90)

In article <0926@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes:
  [ that if a compiler reduces &&**x to x then it is buggy ]

Question for the standards people: Is && undefined, unspecified,
implementation-defined, or what have you? Unless it's simply erroneous,
compilers that always delete &* or *& are only being efficient, and
Wayne's faith in the competence of compiler designers should remain
firm.

---Dan

browns@iccgcc.decnet.ab.com (Stan Brown, Oak Road Systems) (09/12/90)

In article <20757:Sep1115:30:0390@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> 
> Question for the standards people: Is && undefined, unspecified,
> implementation-defined, or what have you? 

See page 49 of K&R 1, or page 53 of K&R 2.

Stan Brown, Oak Road Systems, Cleveland, Ohio, U.S.A.         (216) 371-0043
The opinions expressed are mine. Mine alone!  Nobody else is responsible for
them or even endorses them--except my cat Dexter, and he signed the power of
attorney only under my threat to cut off his Cat Chow!

karl@haddock.ima.isc.com (Karl Heuer) (09/12/90)

In article <20757:Sep1115:30:0390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>In article <0926@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes:
>  [ that if a compiler reduces &&**x to x then it is buggy ]
>
>Question for the standards people: Is && undefined, unspecified,
>implementation-defined, or what have you?

Applying "&" to an operand that is neither a function designator nor an lvalue
violates a constraint (3.3.3.2).  Therefore, a conforming implementation is
required to diagnose an error.

(As with all such diagnostics, it is permissible for it to be a mere warning;
the implementation need not abort the compilation if it chooses to support the
extension that "&*x" is an lvalue.)

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/12/90)

In article <853.26ed0446@iccgcc.decnet.ab.com> browns@iccgcc.decnet.ab.com (Stan Brown, Oak Road Systems) writes:
> In article <20757:Sep1115:30:0390@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> > Question for the standards people: Is && undefined, unspecified,
> > implementation-defined, or what have you? 
> See page 49 of K&R 1, or page 53 of K&R 2.

K&R1 is obviously an incorrect answer, as I was wondering exactly what
level of error-ness &(&(...)) has under ANSI. I don't have K&R2 (does it
really indicate specific error levels?) or the standard, which is why I
was asking in the first place.

I can believe that it's simply erroneous, as it's easy enough for the
compiler to detect. In that case compilers that accept it really are
broken. But is that what the standard settled on?

This is an extremely important question, by the way, as several
implementations would apparently be in violation of conformance if &&
isn't just undefined. They'd be misusing the ``ANSI C'' trademark, and
probably be guilty of false advertising, and maybe even tax evasion.
Remember, this is the very first hint that a compiler might not be
perfectly designed and programmed, or that the implementors might be so
ridiculously incompetent that their programs actually show a b-b-b-bug.
*Extremely* important. *Extremely* incompetent. (Okay, Dan, cut...)

---Dan

pds@lemming.webo.dg.com (Paul D. Smith) (09/12/90)

In some article, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

[]> > Question for the standards people: Is && undefined, unspecified,
[]> > implementation-defined, or what have you? 
[]> See page 49 of K&R 1, or page 53 of K&R 2.
[]
[]K&R1 is obviously an incorrect answer, as I was wondering exactly what
[]level of error-ness &(&(...)) has under ANSI. I don't have K&R2 (does it
[]really indicate specific error levels?) or the standard, which is why I
[]was asking in the first place.
[]
[...]
[]
[]---Dan

Well, I have K&R II, and I didn't see anything on p. 53 which related
to this question ??

However, I did look up some stuff in the reference (Appendix A), which
is where all quotes from K&R II about the ANSI standard should come
from, anyhoo ...  (emphasis added by me)

  Sec. A7.4.2 "Address Operator" (p. 203)

    ... --> The operand must be an lvalue <-- referring neither to a
    bit-field nor to an object declared as register, or must be of
    function type.

  Sec. A7.4.3 "Indirection Operator" (p. 204)

    ... The unary * operator denotes indirection ... --> It is an lvalue
    if the operand is a pointer to an object of arithmetic, structure,
    union, or pointer type <--

So, what does this mean?  This means that

    struct foo *ptr, *ptr2;

    ptr2 = &*ptr;

is definitely legal.  Unfortunately, Sec A7.4.2 does not explicitly
state whether or not "&foo" is an lvalue, although all common sense
would indicate that it is not (can you write "&foo = barp"?  I think
not!)  However, "*" _can_ be applied to something which is not an
lvalue (eg. the name of an array!), and it generates an lvalue.

So,

    ptr = &&&&****ptr2;

is *not* legal (which is fairly intuitive), however it seems that

    ptr = &*&*&*&*ptr2;

_is_ legal.  Whatcha think?
                                                                paul
-----
 ------------------------------------------------------------------
| Paul D. Smith                          | pds@lemming.webo.dg.com |
| Data General Corp.                     |                         |
| Network Services Development           |   "Pretty Damn S..."    |
| Open Network Applications Department   |                         |
 ------------------------------------------------------------------

timr@gssc.UUCP (Tim Roberts) (09/12/90)

In article <20757:Sep1115:30:0390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>In article <0926@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes:
>  [ that if a compiler reduces &&**x to x then it is buggy ]
>
>Question for the standards people: Is && undefined, unspecified,
>implementation-defined, or what have you?

Of course && is defined!  It's the logical "AND" operator!      :-)

And now, back to our regularly scheduled debate.

mwp@ubeaut.oz.au (Michael Paddon) (09/20/90)

From article <165@thor.UUCP>, by scjones@thor.UUCP (Larry Jones):
> It's a very easy mistake to make.  Since both &* and *& are
> essentially noops,

Beware that this is not the case on some architectures. A case in point
is the NCR 32/850 where a location can have two addresses, one in
local memory and one in multibus address space.

You wouldn't believe the grief this can cause...

					Michael

-------------------------------------------------------------------
|                     |     Internet: paddon@meo78b.enet.dec.com  |
|                     |     ACSnet:   mwp@ubeaut.oz.au            |
|  Michael Paddon     |     ACSnet:   mwp@munnari.oz.au           |
|                     |     EasyNet:  meo78b::paddon              |
|                     |     Voice:    +61 3 895 9392              |
-------------------------------------------------------------------

johnhi@teksce.SCE.TEK.COM (John Higley) (09/27/90)

As an experiment, I took the program and fed it to Saber-C.  Using the
browsing tool and a lot of printing, I discovered that each of the &
operators returned an L-value.  Going further, I found that the last one did
not.

Here are the results and a little picture:

addr name contents
    __________
2cf | d  |'d'|
    ----------
2d0 |pd  |2cf|
    ----------
2d4 |ppd |2d0|
    ----------

print &(*(*(ppd)))           --> 2cf
print &(&(*(*(ppd))))        --> 2d0
print &(&(&(*(*(ppd)))))     --> 2d4
print &(&(&(&(*(*(ppd))))))  --> An lvalue (addressable object) is required.

					John Higley
					Tektronix, Inc.
					Component Engineering Group
					johnhi@teksce.SCE.TEK.COM