[comp.lang.c] Is something wrong with the compiler ?

csp@gtenmc.UUCP (csp) (09/26/90)

   Assuming that the 2's complement system is used to represent the negative
   integers. I wrote the following code , and the results I got were absurd.

C code :

   main()
   {
      int a;
      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
   }

 Output :

    Maxint : -1 
    a = 2147483647 

Can some complier writer tell me why this is happening ?

csp - csp@gtenmc.UUCP

K&R C > ANSI C

eager@ringworld.Eng.Sun.COM (Michael J. Eager) (09/26/90)

In article <884@gtenmc.UUCP> csp@gtenmc.UUCP (Charudutta S Palkar) writes:
>
>   Assuming that the 2's complement system is used to represent the negative
>   integers. I wrote the following code , and the results I got were absurd.
>
>C code :
>
>   main()
>   {
>      int a;
>      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
>	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
>   }
>
> Output :
>
>    Maxint : -1 
>    a = 2147483647 
>
>Can some complier writer tell me why this is happening ?
>
>csp - csp@gtenmc.UUCP
>
>K&R C > ANSI C

The right shift operator is not clearly defined when applied to 
signed integers.  It looks like your compiler does a logical
right shift, which inserts a high order zero bit.  

The assignment of a = ~0 will make a = -1.  When this is shifted
right by one bit, and the sign bit is set to zero, a becomes
MAXINT, which you then converted to unsigned and then int, neither
of which change its value.  

-- Mike Eager

bomgard@iuvax.cs.indiana.edu (Tim Bomgardner) (09/26/90)

In article <884@gtenmc.UUCP> csp@gtenmc.UUCP (Charudutta S Palkar) writes:
}
}   Assuming that the 2's complement system is used to represent the negative
}   integers. I wrote the following code , and the results I got were absurd.
}
}C code :
}
}   main()
}   {
}      int a;
}      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
}	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
}   }
}
} Output :
}
}    Maxint : -1 
}    a = 2147483647 
}
}Can some complier writer tell me why this is happening ?
}
}csp - csp@gtenmc.UUCP
}
}K&R C > ANSI C


The value for a is exactly what I would expect: pow(2,31)-1.  The question
is is ~0 in the expression ((unsigned) ~0 >> 1) signed or unsigned.  If it
is signed, then the result is implementation-defined and can be either a
logical or an arithmetic shift.  -1 is the correct result for an 
arithmetic shift.  However, you have a valid cast, so ~0 is unsigned and
a logical shift should be performed.  I believe your compiler is in error.

henry@zoo.toronto.edu (Henry Spencer) (09/27/90)

In article <884@gtenmc.UUCP> csp@gtenmc.UUCP (Charudutta S Palkar) writes:
>   ... I wrote the following code , and the results I got were absurd.
>
>      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
>	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));

Sure you know what the results should be?  The second expression is
assigning to `a' twice, which has unpredictable effects.  However, this
doesn't explain what you're seeing.  It does look to me like a compiler
bug.
-- 
TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology
OSI: handling yesterday's loads someday|  henry@zoo.toronto.edu   utzoo!henry

burley@world.std.com (James C Burley) (09/27/90)

In article <1990Sep26.175948.8232@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:

   In article <884@gtenmc.UUCP> csp@gtenmc.UUCP (Charudutta S Palkar) writes:
   >   ... I wrote the following code , and the results I got were absurd.
   >
   >      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
   >	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));

   Sure you know what the results should be?  The second expression is
   assigning to `a' twice, which has unpredictable effects.  However, this
   doesn't explain what you're seeing.  It does look to me like a compiler
   bug.

Hmm, I thought it was ok -- doesn't "=" serve as a "sequence point" or
some such thing, and since the lhs of the outer = is so simple it can't
be "evaluated" before the rhs has been, and the rhs contains the other
=, one is guaranteed the latter = is performed before the former, right?

On the other hand, "b = a + (int)((unsigned)(a=~0)>>1));" would be undefined
as to whether the first mention of "a" identifies the value it holds prior
to execution of the statement or the value ~0.

James Craig Burley, Software Craftsperson    burley@world.std.com

henry@zoo.toronto.edu (Henry Spencer) (09/27/90)

In article <143014@sun.Eng.Sun.COM> eager@ringworld.Eng.Sun.COM (Michael J. Eager) writes:
>>      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
>The assignment of a = ~0 will make a = -1.  When this is shifted
>right by one bit, and the sign bit is set to zero, a becomes
>MAXINT, which you then converted to unsigned and then int...

Careful...  Casts bind tighter than binary operators; the unsigned
conversion is being done *before* the shift.
-- 
TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology
OSI: handling yesterday's loads someday|  henry@zoo.toronto.edu   utzoo!henry

benyukhi@motcid.UUCP (Ed Benyukhis) (09/28/90)

In article <143014@sun.Eng.Sun.COM>, eager@ringworld.Eng.Sun.COM (Michael J. Eager) writes:
> In article <884@gtenmc.UUCP> csp@gtenmc.UUCP (Charudutta S Palkar) writes:
> >      int a;
> >      printf(" Maxint : %d\na = %d\n", ( int )(( unsigned ) ~0 >> 1 ) , 
> >	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
> > Output :
> >    Maxint : -1 
> >    a = 2147483647 
> >Can some complier writer tell me why this is happening ?
> 
> The right shift operator is not clearly defined when applied to 
> signed integers.  It looks like your compiler does a logical
> right shift, which inserts a high order zero bit.  




On the contrary, it looks like his compiler does an arithmetic shifts which
sign extends i.e. fills vacated bits with the original sign bit.  This problem
really concerns the "right shifts on signed operands".  The language permits
the shift to be implemented as an arithmetic shift operation or a logical
shift (fill vacated bits with 0's).  The choice is left to the compiler
writer.  "When the left operand of >> is an unsigned type, C mandates a
logical shift".  Thus declaring a variable to be an unsigned type yields
uniform behavior.  




Ed Benyukhis

henry@zoo.toronto.edu (Henry Spencer) (09/28/90)

In article <BURLEY.90Sep27013312@world.std.com> burley@world.std.com (James C Burley) writes:
>   Sure you know what the results should be?  The second expression is
>   assigning to `a' twice, which has unpredictable effects...
>
>Hmm, I thought it was ok -- doesn't "=" serve as a "sequence point" or
>some such thing, and since the lhs of the outer = is so simple it can't
>be "evaluated" before the rhs has been, and the rhs contains the other
>=, one is guaranteed the latter = is performed before the former, right?

Wrong.  Assignment is not a sequence point.  Furthermore, taking the
value of an assignment is no guarantee that the assignment has been
performed.  It's quite legal for the compiler to save up all the assignments
and do them at the end of the expression, if that happens to be more
convenient.  The only constraint is that the update to the lhs must occur
somewhere between the previous and the next sequence point.

In the absence of intervening sequence points (*some* operators do cause
them), the result of modifying an object's value more than once in the same
expression is specifically undefined.  It might work.  It might fail.  It
might work only when the Moon is full.  It might use your modem to place
a call to the Pentagon and request an airstrike on your house. :-)
-- 
Imagine life with OS/360 the standard  | Henry Spencer at U of Toronto Zoology
operating system.  Now think about X.  |  henry@zoo.toronto.edu   utzoo!henry

kelley@molecules.ecn.purdue.edu (Stephen Kelley) (09/29/90)

In article <1990Sep28.151723.24287@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
	[about the definition of 'undefined']
-
-                                         It might use your modem to place
- a call to the Pentagon and request an airstrike on your house. :-)
- -- 

No doubt this is the ANSI version of Chris Torek's "...make your 
monitor explode."

Steve Kelley		kelley@flowcyt.ecn.purdue.edu

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

In article <BURLEY.90Sep27013312@world.std.com>, burley@world.std.com (James C Burley) writes:
>    >	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
> 
> Hmm, I thought it was ok -- doesn't "=" serve as a "sequence point" or
> some such thing, and since the lhs of the outer = is so simple it can't
> be "evaluated" before the rhs has been, and the rhs contains the other
> =, one is guaranteed the latter = is performed before the former, right?

No, '=' is not a sequence point.  The question in this case is not when
the lhs gets evaluated, but when the actual storage of the rhs into the
lhs is done.  A compiler would be completely within its rights to store
the final result into a and then overwrite it with ~0.
----
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
Yep, we'd probably be dead by now if it wasn't for Twinkies. -- Calvin

hp@vmars.tuwien.ac.at (Peter Holzer) (10/02/90)

scjones@thor.UUCP (Larry Jones) writes:

>In article <BURLEY.90Sep27013312@world.std.com>, burley@world.std.com (James C Burley) writes:
>>    >	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
>> 

>No, '=' is not a sequence point.  The question in this case is not when
>the lhs gets evaluated, but when the actual storage of the rhs into the
>lhs is done.  A compiler would be completely within its rights to store
>the final result into a and then overwrite it with ~0.

Yes, but the variable 'a' was not used afterwards, so we are not
interested in the value of a, but in the value of the complete
expression, which is IMHO well defined (The standard says in 3.3.16:
An assignment expression has the value of the left operand after the
assignment).

Expression:					Value:
(a = ~0)					(int) ~0
(unsigned)(a = ~0)				(unsigned) ~0
((unsigned)(a = ~0) >> 1)			(unsigned) MAXINT
(int)((unsigned)(a = ~0) >> 1)			(int) MAXINT
a = (int)((unsigned)(a = ~0) >> 1)		(int) MAXINT

Anything wrong with my reasoning?
--
|    _	| Peter J. Holzer			| Think of it	|
| |_|_)	| Technische Universitaet Wien		| as evolution	|
| | |	| hp@vmars.tuwien.ac.at			| in action!	|
| __/  	| ...!uunet!mcsun!tuvie!vmars!hp	|     Tony Rand	|

msb@sq.sq.com (Mark Brader) (10/03/90)

> > >         a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
> > Sure you know what the results should be?  The ... expression is
> > assigning to `a' twice, which has unpredictable effects.

> Hmm, I thought it was ok -- doesn't "=" serve as a "sequence point" or
> some such thing, and since the lhs of the outer = is so simple it can't
> be "evaluated" before the rhs has been, and the rhs contains the other
> =, one is guaranteed the latter = is performed before the former, right?

Wrong.  First, assignment does not cause a sequence point.  The only
sequence points are:

        [1] After evaluating an expression that is not part of another
            expression; for instance, after an expression statement or
            after any one of the expressions in a for-header.

        [2] After evaluating the first operand of one of the operators
            "?"/":", "&&", "||", "," (conditional expression, logical
            and/or, or comma).

        [3] After evaluating the arguments of a function and before
            calling the function.  (Note that the comma between the
            arguments is not a comma operator, so the arguments may
            be evaluated in any order, and had better not alter the
            same variable more than once.

Second, even if the rhs did have to be evaluated first, this would not
imply that *side-effects* of its evaluation would be executed before
the next sequence point.  The compiler is free to interpret

           a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));

as if it was written

           a = ( int )(( unsigned ) ( tmpa = ~0 ) >> 1 ));
           a = tmpa;

(where tmpa is an otherwise unused variable of the same type as a).

Note incidentally that statements like

           p = p->f = newp;
and
           p->f = p = newp;

have undefined effect for the same reason.  If you find yourself writing
something like this, you should break it up into two statements.
-- 
Mark Brader		     "It is impractical for the standard to attempt to
SoftQuad Inc., Toronto	      constrain the behavior of code that does not obey
utzoo!sq!msb, msb@sq.com      the constraints of the standard."  -- Doug Gwyn

This article is in the public domain.

kdq@demott.COM (Kevin D. Quitt) (10/03/90)

In article <1895@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
>
>Expression:					Value:
>(a = ~0)					(int) ~0
>(unsigned)(a = ~0)				(unsigned) ~0
>((unsigned)(a = ~0) >> 1)			(unsigned) MAXINT
>(int)((unsigned)(a = ~0) >> 1)			(int) MAXINT
>a = (int)((unsigned)(a = ~0) >> 1)		(int) MAXINT
>
>Anything wrong with my reasoning?

    Yes.  Undefined order or assignment means undefined.  It is
perfectly legitimate for the (a = ~0) assignment to actually take place
after the a = (int)((unsigned)(a = ~0) >> 1) assignment.  That's what
undefined order means. 

    I agree that a proper compiler "knows" that the former is
unnecessary, and can/will be optimized away, but a compiler that isn't
that smart *isn't* broken (according to the spec).

-- 
 _
Kevin D. Quitt         demott!kdq   kdq@demott.com
DeMott Electronics Co. 14707 Keswick St.   Van Nuys, CA 91405-1266
VOICE (818) 988-4975   FAX (818) 997-1190  MODEM (818) 997-4496 PEP last

                96.37% of all statistics are made up.

rmj@tcom.stc.co.uk (The Beardless Wonder) (10/03/90)

In article <1895@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
}scjones@thor.UUCP (Larry Jones) writes:
}
}>In article <BURLEY.90Sep27013312@world.std.com>, burley@world.std.com (James C Burley) writes:
}>>    >	      a = ( int )(( unsigned ) ( a = ~0 ) >> 1 ));
}>> 
}
}>No, '=' is not a sequence point.  The question in this case is not when
}>the lhs gets evaluated, but when the actual storage of the rhs into the
}>lhs is done.  A compiler would be completely within its rights to store
}>the final result into a and then overwrite it with ~0.
}
}Yes, but the variable 'a' was not used afterwards, so we are not
}interested in the value of a, but in the value of the complete
}expression, which is IMHO well defined (The standard says in 3.3.16:
}An assignment expression has the value of the left operand after the
}assignment).

The whole point is that "Afterwards" is not a well-defined concept here.
The value of the assignment expression is as you say, but as Larry says
the value that 'a' has on the far side of the semicolon could be ~0
without contravening the standard.
-- 
* Windsinger                 * "But soft, what light through yonder
* rmj@islay.tcom.stc.co.uk   *      airlock breaks?"
* rmj@tcom.stc.co.uk         *    --RETURN TO THE FORBIDDEN PLANET
* rmj10@phx.cam.ac.uk        *  You've gotta be cruel to be Khund!

henry@zoo.toronto.edu (Henry Spencer) (10/04/90)

In article <1895@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
>... the variable 'a' was not used afterwards, so we are not
>interested in the value of a, but in the value of the complete
>expression, which is IMHO well defined ...

By the 3.3 introduction, and the definition of the meaning of "shall"
outside constraints, it's not just the value of `a' that is undefined,
but the behavior of the entire expression.
-- 
Imagine life with OS/360 the standard  | Henry Spencer at U of Toronto Zoology
operating system.  Now think about X.  |  henry@zoo.toronto.edu   utzoo!henry

hp@vmars.tuwien.ac.at (Peter Holzer) (10/05/90)

kdq@demott.COM (Kevin D. Quitt) writes:

>In article <1895@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
>>
>>Expression:					Value:
>>(a = ~0)					(int) ~0
>>(unsigned)(a = ~0)				(unsigned) ~0
>>((unsigned)(a = ~0) >> 1)			(unsigned) MAXINT
>>(int)((unsigned)(a = ~0) >> 1)			(int) MAXINT
>>a = (int)((unsigned)(a = ~0) >> 1)		(int) MAXINT
>>
>>Anything wrong with my reasoning?

>    Yes.  Undefined order or assignment means undefined.  It is
>perfectly legitimate for the (a = ~0) assignment to actually take place
>after the a = (int)((unsigned)(a = ~0) >> 1) assignment.  That's what
>undefined order means. 

I got several replies saying about the same by email, and I think none
really covered the point I was making so I will give it a second try
with a simpler example:

Consider the following expression (initial value of a is 0):

a = (a = a + 1) + 1

This will compile (unoptimized) into:

tmp1 = a + 1
a = tmp1	*
tmp2 = tmp1 + 1
a = tmp2	*

where the lines marked with * may or may not be deferred until the next
sequence point, making the final value of a undefined, but the value of
the whole expression is the value of tmp2, which is not changed by
moving the * lines around.

The value of (a = a + 1) is 1, the actual assignment takes place
sometime before the next sequence point (But we do not know when).

So the whole expression (a = (a = a + 1) + 1) becomes (a = (1) + 1)
and the value is 2. Again, the assignment a = 2 takes place at some time
before the next sequence point. So what we have is that the expression
has the value 2, but a may have the value 1 or 2, depending on which
assignment takes place first.


On the other hand, if we have an expression like

(a = a + 1) + (a = a + 1)

it will become:

tmp1 = a + 1
a = tmp1	*
tmp2 = a + 1
a = tmp2	*
tmp3 = tmp1 + tmp2

If in this case the compiler decides tho move the line `a = tmp1' the
value of tmp2 and thus also the value of tmp3 (which is the value of the
whole expression) will change.

The compiler might use the initial value for a in both assignments so
that the result would be (1) + (1) == 2, or it might evaluate the left
subexpression (or the right, doesn't matter in this case), then assign
the new value to a, then evaluate the other subexpression with the new
value of a, yielding (1) + (2) == 3.

Any further comments?

--
|    _	| Peter J. Holzer			| Think of it	|
| |_|_)	| Technical University Vienna		| as evolution	|
| | |	| Dept. for Real-Time Systems  		| in action!	|
| __/  	| hp@vmars.tuwien.ac.at			|     Tony Rand	|

chris@mimsy.umd.edu (Chris Torek) (10/06/90)

In article <1903@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
>Consider ... a = (a = a + 1) + 1
>This will compile (unoptimized) into:
>
>tmp1 = a + 1
>a = tmp1	*
>tmp2 = tmp1 + 1
>a = tmp2	*
>
>where the lines marked with * may or may not be deferred until the next
>sequence point....  [Second example deleted.] ... Any further comments?

Yes.  The ANSI standard appears% to allow the compiler to compile it
as

	tmp0 = a
	tmp1 = tmp0 + 1
	a = rand()	*
	tmp2 = tmp0 + 2
	a = tmp2	*

(using the same notation as above).  If the store of tmp2 happens
before the store of tmp1, a could wind up with a random value.

For a more realistic example, consider a machine that can do several
operations at once.  This machine might issue two separate
`simultaneous' operations, those being `increment a' and `set a=a+2'.
This could fetch the value of `a' after the increment has changed only
part of the ultimate value (assume it is a parallel machine with lots
of one-bit CPUs).  The end result is that dreaded word, `undefined'.

In short, when the ANSI standard says that the result of an operation
is undefined, it means UNDEFINED.  The computer can do anything (like
turn into a flower)---the system does not have to do anything remotely
reasonable.  When it says a result is implementation-defined, the
system can still do anything, but the product description has to tell
you what it does.

-----
% Note weasel word.  :-)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

wald@theory.lcs.mit.edu (David Wald) (10/07/90)

In article <26875@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
>In short, when the ANSI standard says that the result of an operation
>is undefined, it means UNDEFINED.  The computer can do anything (like
>turn into a flower)---the system does not have to do anything remotely
>reasonable.

I'm continually amused by the examples people give for undefined and
implementation-defined behavior.  Can we get a list together, possibly
to be incorporated into an Emacs macro?

Examples:

  Melt your screen;
  Call your mother;
  Send nasty notes to your boss;
  ...?


-David


``The `#pragma' command is specified in the ANSI standard to have an
arbitrary implementation-defined effect.  In the GNU C preprocessor,
`#pragma' first attempts to run the game `rogue';  if that fails, it
tries to run the game `hack'; if that fails, it tries to run GNU Emacs
displaying the Tower of Hanoi; if that fails, it reports a fatal
error.  In any case, preprocessing does not continue.''
       -- from the manual for the GCC preprocessor (GCC version 1.34)



--
============================================================================
David Wald                                           wald@theory.lcs.mit.edu
============================================================================

meissner@osf.org (Michael Meissner) (10/07/90)

In article <1990Oct6.194120.27656@mintaka.lcs.mit.edu>
wald@theory.lcs.mit.edu (David Wald) writes:

| In article <26875@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
| >In short, when the ANSI standard says that the result of an operation
| >is undefined, it means UNDEFINED.  The computer can do anything (like
| >turn into a flower)---the system does not have to do anything remotely
| >reasonable.
| 
| I'm continually amused by the examples people give for undefined and
| implementation-defined behavior.  Can we get a list together, possibly
| to be incorporated into an Emacs macro?
| 
| Examples:
| 
|   Melt your screen;
|   Call your mother;
|   Send nasty notes to your boss;
|   ...?

I tend to use delete the offending source file, after running into an
alpha version of a compiler that did that when given a certain invalid
switch.

| ``The `#pragma' command is specified in the ANSI standard to have an
| arbitrary implementation-defined effect.  In the GNU C preprocessor,
| `#pragma' first attempts to run the game `rogue';  if that fails, it
| tries to run the game `hack'; if that fails, it tries to run GNU Emacs
| displaying the Tower of Hanoi; if that fails, it reports a fatal
| error.  In any case, preprocessing does not continue.''
|        -- from the manual for the GCC preprocessor (GCC version 1.34)

Gcc now does recognize at least one pragma (#pragma once).  Here's
what's in the source, where it keeps the code around, but #if'ed out:

#if 0
/* This was a fun hack, but #pragma seems to start to be useful.
   By failing to recognize it, we pass it through unchanged to cc1.  */

/*
 * the behavior of the #pragma directive is implementation defined.
 * this implementation defines it as follows.
 */
do_pragma ()
{
  close (0);
  if (open ("/dev/tty", O_RDONLY, 0666) != 0)
    goto nope;
  close (1);
  if (open ("/dev/tty", O_WRONLY, 0666) != 1)
    goto nope;
  execl ("/usr/games/hack", "#pragma", 0);
  execl ("/usr/games/rogue", "#pragma", 0);
  execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
  execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
nope:
  fatal ("You are in a maze of twisty compiler features, all different");
}
#endif
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

Do apple growers tell their kids money doesn't grow on bushes?

friedl@mtndew.Tustin.CA.US (Steve Friedl) (10/09/90)

> /*
>  * the behavior of the #pragma directive is implementation defined.
>  * this implementation defines it as follows.
>  */
>
>   execl ("/usr/games/hack", "#pragma", 0);
                                        ^^^
Can somebody please tell GNU about uncasted NULL pointers?


     Steve

-- 
Stephen J. Friedl, KA8CMY / I speak for me only / Tustin, CA / 3B2-kind-of-guy
+1 714 544 6561  / friedl@mtndew.Tustin.CA.US  / {uunet,attmail}!mtndew!friedl

"No job is too big, no fee is too big" - Gary W. Keefe's company motto

hp@vmars.tuwien.ac.at (Peter Holzer) (10/09/90)

chris@mimsy.umd.edu (Chris Torek) writes:

>In article <1903@tuvie> hp@vmars.tuwien.ac.at (Peter Holzer) writes:
>>Consider ... a = (a = a + 1) + 1
>>This will compile (unoptimized) into:
>>
>>tmp1 = a + 1
>>a = tmp1	*
>>tmp2 = tmp1 + 1
>>a = tmp2	*
>>
>>where the lines marked with * may or may not be deferred until the next
>>sequence point....  [Second example deleted.] ... Any further comments?

>Yes.  The ANSI standard appears% to allow the compiler to compile it
>as

>	tmp0 = a
>	tmp1 = tmp0 + 1
>	a = rand()	*
>	tmp2 = tmp0 + 2
>	a = tmp2	*

Even in this case the the value of the expression (= tmp2) has the expected
value (original value of a) + 2.

But in the meantime I have found the following sentence in the introduction
to chapter 3.3 (Thanks to Henry Spencer who told me to look there):

	Between the previous and next sequence point an object shall
	have its stored value modified at most once by the evaluation of
	an expression.

Together with the sentence in 1.6

	Permissible undefined behaviour ranges from ignoring the
	situation completely with undefined results [...] to terminating
	a translation or execution [...].

this means that the program might not even compile, or do one or more of
the exciting things proposed for undefined behaviour by various people
in this group.

If however, the compiler decides to be nice to the programmer, and
compiles the program to something that has anything to do with the
source code, I think that after executing the statements:

int a = 0, b;
b = (a = (a = a + 1) + 1);

b will have the value 2, and a will have a random value (but any other
value than 1 or 2 is not very propable).

Thanks to all who answered me, I learned something about C again.

Regards,
	Peter.

--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

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

In article <542@mtndew.Tustin.CA.US> friedl@mtndew.Tustin.CA.US (Steve Friedl) writes:
> > /*
> >  * the behavior of the #pragma directive is implementation defined.
> >  * this implementation defines it as follows.
> >  */
> >   execl ("/usr/games/hack", "#pragma", 0);
> Can somebody please tell GNU about uncasted NULL pointers?

In case you didn't notice, this behavior is *supposed* to be
implementation-defined. The code looks right to me... :-)

---Dan