[comp.lang.c] ! operator in constant expressions

gnu@hoptoad.uucp (John Gilmore) (01/10/88)

I just wrote an interesting test program for ! and haven't yet found
a compiler that correctly implements the draft ANSI standard for it.
Try it on yours, and let me know (if it works -- I already believe it
will fail).  If anyone can show me how this program is not fully
conformant to the draft standard, I would also like to know.


int install = !0;	/* Gcc 1.16 said "initializer is not constant" */
			/* Gcc 1.17 gets wrong answer! */
char foo = !1;
int bar = !3.14156;	/* SunOS 3.3 cc said "Illegal initialization" */
int pno = ! &bar;	/* Gcc 1.17 said "initializer for static variable
			   uses complex arithmetic" */
int pyes = !(char *)0;

main() {
	if (install && !foo && !bar && pyes && !pno)
		printf("Test passed\n");
	else
		printf("FAILED, install=%d, foo=%d, bar=%d, pno=%d, pyes=%d\n",
			install, foo, bar, pno, pyes);
}
-- 
{pyramid,ptsfa,amdahl,sun,ihnp4}!hoptoad!gnu			  gnu@toad.com
  I forsee a day when there are two kinds of C compilers: standard ones and 
  useful ones ... just like Pascal and Fortran.  Are we making progress yet?
	-- ASC:GUTHERY%slb-test.csnet

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/11/88)

In article <3813@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>I just wrote an interesting test program for ! and haven't yet found
>a compiler that correctly implements the draft ANSI standard for it.
>int install = !0;
>char foo = !1;

I left the draft standard in my other trousers, but I'm sure that
the above two should work, with values 1 and 0 in that order.

>int bar = !3.14156;
>int pno = ! &bar;
>int pyes = !(char *)0;

I don't see how you could expect any of these three to work; the
operand of ! has to be an integer, which might be obtained by
promotion but never by demotion or assumed type conversion of
pointers.

gwyn@brl-smoke.UUCP (01/12/88)

In article <7027@brl-smoke.ARPA>, I wrote:
> In article <3813@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
> >int bar = !3.14156;
> >int pno = ! &bar;
> >int pyes = !(char *)0;
> I don't see how you could expect any of these three to work; the
> operand of ! has to be an integer ...

My only excuse is that I was very ill when I wrote that!
Of course, one all the time sees code like
	type *p;
	if (!p) ...
My personal practice is to apply ! only to "Boolean expressions",
which is not something that C officially understands, but it's
easy to self-impose the "Boolean" discipline, and beneficial to
code quality and maintenance.  However, just because I never apply
! to a non-integer (which is a superset of Boolean in C), doesn't
mean that it is prohibited by the language spec.

Now that I can check the dpANS, I find that an initializer for a
scalar is constrained to be a constant-expression, and otherwise
the same type constraints and conversions apply as for simple
assignment.  Also, !E is equivalent to E==0.  Thus, all the above
examples are supposedly legal in ANSI C.  I apologize for my
earlier mistake.

steve@endor.harvard.edu (Kaufer - Lopez - Pratap) (01/12/88)

In article <3813@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>I just wrote an interesting test program for ! and haven't yet found
>a compiler that correctly implements the draft ANSI standard for it.
>Try it on yours, and let me know (if it works -- I already believe it
>will fail).  

Saber-C, an interpreter based development environment for C, runs this
program perfectly.  ANSI constructs that are not compatible with pcc
(such as argument widening for functions with prototypes) are also
available by specifying the appropriate Saber-C option.

[Saber-C runs on vax and sun machines running ultrix/unix.]

	- Steve Kaufer
	Saber Software, Inc.
	saber@harvard.harvard.edu
	{ihnp4, decvax, husc6}!harvard!steve

sue@hpclsue.HP.COM (Sue Meloy) (01/13/88)

According to the latest ANSI draft:

A constant expression used in a static initializer must evaluate to one of the
following:

    an arithmetic constant expression
        only arithmetic operands; casts can only be from arithmetic type to
        arithmetic type.
    an address constant
	created via & or by use of an array or function name
    an address constant plus or minus an integral constant expression

Thus, the following examples are not legal ANSI C:

int pno = ! &bar;
int pyes = !(char *)0; 

	Sue Meloy
	sue@hpda.HP.COM

am@cl.cam.ac.uk (Alan Mycroft) (01/29/88)

I hope the public review draft is a little more precise....

In article <660003@hpclsue.HP.COM> sue@hpclsue.HP.COM (Sue Meloy) writes:
>According to the latest ANSI draft:
>A constant expression used in a static initializer must evaluate to one of
****                                                     ^^^^^^^^ Duh?
>the following:
>    an arithmetic constant expression
>        only arithmetic operands; casts can only be from arithmetic type to
>        arithmetic type.
>    an address constant
>	created via & or by use of an array or function name
****                                                    ^^^^
0. Presumably static.
1. Or array expression?   Consider
         static struct { int a, b[5]; } x;  int *p = x.b;
2. Presumably all subscripts must be arith. const. exprs?
3. What about  static int a,*b = &*&a;
>    an address constant plus or minus an integral constant expression
****
0. Presumably this applies recursively so that
         static int a[10], *b = (&a[0] + 6) - 4;
   is OK?