[comp.std.c] What is a constant expression

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (10/18/89)

  Trying to get a net program working has brought up an interesting
question as to what is a constant expression.

  Background: large program, defines ASCII control characters with a
macro as follows:
	#define CNTL(c) ('c' & 037)
While this work fine with pcc, the ANSI preprocessor doesn't expand it.
I know that there is now a way to expand to a string, so I looked for
the way to expand to a character. I dind't find it. Therefore, rather
than plow through thousands of lines of someone else's code to change
all occurences, I redefined the macro as:
	#define CNTL(c) (#c[0] & 037)

  This expands as follows: CNTL(M) becomes ("M"[0] & 037). No problem,
the string is a constant, the subscript is a constant, the octal value
is a constant, and the compiler was happy. Except... where the macro was
used to initialize a static value, in which case it was "not a constant
expression."

  What am I missing in the standard? In looking up initializers in the
index, section 3.5.7 (L14) uses the term "constant expression." However
the index doesn't seem to list that term. I looked in the expressions
section and didn't find it. Obviously my assumption that it is an
expression made up entirely of elements whose value is known at compile
time" is incorrect.

  Don't waste your time telling me that's a bad way to do the macro, I
didn't write it, and I don't defend it.
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon

henry@utzoo.uucp (Henry Spencer) (10/19/89)

In article <1219@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:
>  What am I missing in the standard? In looking up initializers in the
>index, section 3.5.7 (L14) uses the term "constant expression." However
>the index doesn't seem to list that term...

Wonderful index, that... :-(  Try the table of contents:  section 3.4 is
all about constant expressions.  Unfortunately, subscripting a string isn't
one.
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

diamond@csl.sony.co.jp (Norman Diamond) (10/19/89)

In article <1219@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:

>	#define CNTL(c) ('c' & 037)
>While this work fine with pcc, the ANSI preprocessor doesn't expand it.

Another way around it is to edit all the calls to CNTL(c) to look like
CNTL('c'), which isn't too difficult a change.  Then the macro depends
on neither Reiser nor ANSI stringizing, and the expression is obviously
constant.  (Uh, obviously, obviously, hmm, can't find "obviously" in the
index to the draft standard, bet someone will bite us on this too.)

-- 
Norman Diamond, Sony Corp. (diamond%ws.sony.junet@uunet.uu.net seems to work)
  Should the preceding opinions be caught or     |  James Bond asked his
  killed, the sender will disavow all knowledge  |  ATT rep for a source
  of their activities or whereabouts.            |  licence to "kill".

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/19/89)

In article <1219@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:
>	#define CNTL(c) ('c' & 037)

>  What am I missing in the standard? In looking up initializers in the
>index, section 3.5.7 (L14) uses the term "constant expression." However
>the index doesn't seem to list that term.

Sure it does:
	constant expressions, 3.4

>  Don't waste your time telling me that's a bad way to do the macro, I
>didn't write it, and I don't defend it.

My recommendation for this abuse of the preprocessor, widely encountered
in code from Berkeley UNIX systems, is to change the macro to
	#define CNTRL(c) ((c) & 037)
then globally edit the source code to wrap the arguments with '',
e.g. in "ed":
	g/CTRL(/s/CTRL(\(.\))/CNTRL('\1')/g

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (10/19/89)

In article <1989Oct18.224801.1767@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
|  
|  Wonderful index, that... :-(  Try the table of contents:  section 3.4 is
|  all about constant expressions.  Unfortunately, subscripting a string isn't
|  one.

  I blush... I looked in the index and not the TOC. I suspect that I'm
not the only one who thinks the index should be about three times longer
than it is... I feel particularly dumb because I believe I quoted
footnote 44 as part of another posting on sizeof something with a NULL
pointer.

  While the wording in 3.4 is not explicit on this particular case, by
looking at what is allowed and forbidden I conclude that "abcd"[1] is
not treated as a character constant. It would be nice if it was, but it
is treated as if I had said:

	char nameless[] = "abcd";
	char foo = nameless[1];

which clearly isn't allowed for static init.

  I would like to know if the committee considered the indexed string
constant and decided not to make it a special case, or just didn't
think of it when doing this section. Obviously it's not one of the
common uses ;-)
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon

dan@oresoft.uu.net (Daniel Elbaum) (10/20/89)

In article <1219@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:
:
:  Trying to get a net program working has brought up an interesting
:question as to what is a constant expression.

<the expression>:

:	#define CNTL(c) (#c[0] & 037)
:
:  This expands as follows: CNTL(M) becomes ("M"[0] & 037). No problem,
:the string is a constant, the subscript is a constant, the octal value
:is a constant, and the compiler was happy. Except... where the macro was
:used to initialize a static value, in which case it was "not a constant
:expression."
:
:  What am I missing in the standard? In looking up initializers in the
:index, section 3.5.7 (L14) uses the term "constant expression." However
:the index doesn't seem to list that term. I looked in the expressions
:section and didn't find it. Obviously my assumption that it is an
:expression made up entirely of elements whose value is known at compile
:time" is incorrect.

Referring to the 12/88 dpANS:

It's listed under "constant" in the index, of course. :-)

Section 3.4 describes basically three kinds of constant expressions
that can be used in initializers: arithmetic constants, null pointer
constants, and address constants plus or minus integral constants.
Arithmetic constant expressions can only contain integral constant
operands, so they're out.  Address constants point to static storage
or to functions, and can contain [], ., ->, &, and *, but you're not
allowed to use the values of objects obtained by using them.

	I guess XJ311 didn't want to bother distinguishing between
constant-pointer-to-constant-object and constant-pointer-to-
arbitrary-object for compile-time rules.


-- 
Spa link snot the temper tent, a few cannery doubt lowed.

({uunet,tektronix,reed,sun!nosun,osu-cis,psu-cs}!oresoft!(dan)@oresoft.uu.net)

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/20/89)

In article <1262@crdos1.crd.ge.COM> davidsen@crdos1.UUCP (bill davidsen) writes:
>In article <1989Oct18.224801.1767@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
>|  Wonderful index, that... :-(  Try the table of contents:  ...
>  I blush... I looked in the index and not the TOC.

Is there something wrong with you guys, or is there a problem in the copy
of the draft proposed Standard that you have?  The index in my copy does
have "constant expressions", right after the list of "constant, ..." entries.

dg@lakart.UUCP (David Goodenough) (10/21/89)

From article <1219@crdos1.crd.ge.COM>, by davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr):
>   Background: large program, defines ASCII control characters with a
> macro as follows:
> 	#define CNTL(c) ('c' & 037)
> While this work fine with pcc, the ANSI preprocessor doesn't expand it.

This is:

1. Grotesque,

2. Workable.

Flame away if you wish, just try it first.

#define	prequote(x) 'x
#define postquote(x) x'

#define	CNTL(c) ((postquote(prequote(c))) & 0x1f)

CNTL(c)

Bletch :-/

MAJOR MAJOR PROBLEM - our C compiler (greenhills) likes the useages of
postquote and prequote in that order. Some compilers may not care, while
others might want them reversed. I think it depends on whether nested
macros are expanded from the inside out (as Greenhills does), or outside
in.

It's probably not portable .... Oh well.
-- 
	dg@lakart.UUCP - David Goodenough		+---+
						IHS	| +-+-+
	....... !harvard!xait!lakart!dg			+-+-+ |
AKA:	dg%lakart.uucp@xait.xerox.com			  +---+

kremer@cs.odu.edu (Lloyd Kremer) (10/21/89)

In article <1219@crdos1.crd.ge.COM> davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) writes:

>	#define CNTL(c) ('c' & 037)
>While this work fine with pcc, the ANSI preprocessor doesn't expand it.
>
>	#define CNTL(c) (#c[0] & 037)
>
>  This expands as follows: CNTL(M) becomes ("M"[0] & 037).
>where the macro was
>used to initialize a static value, in which case it was "not a constant
>expression."
>
>Obviously my assumption that it is an
>expression made up entirely of elements whose value is known at compile
>time" is incorrect.


This seemed like an interesting question, and I've been waiting for a response
from one of the real "legal eagles" of the Standard.  But since none is
forthcoming, I'll throw in my two cents.

The macro contains an array subscripting expression, and the compiler 
apparently fears that the contents of the array may be changed at run time
rendering the expression non-constant.  However, notice that the array in
question is a *string literal*.  What is this compiler's policy regarding
the writability of string literals?

If they are writable, then the compiler's rejection of the expression is
justified.  If they are not, then the compiler is simply seeing the
subscripting operation, and prematurely giving up hope of constancy.

Of course, neither possibility offers a solution.  The compiler won't accept
to expression as constant.

I don't suppose it would do any good to put a "const" into the macro.

Just hypothesizing.  :-)


P.S. I support the adoption of the Standard, but it is disheartening to keep
seeing its introduction cause working code to break.  Growing pains, I guess.

-- 
					Lloyd Kremer
					...!uunet!xanth!kremer
					Have terminal...will hack!

djones@megatest.UUCP (Dave Jones) (10/21/89)

From article <1219@crdos1.crd.ge.COM>, by davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr):
> 
...
>   Background: large program, defines ASCII control characters with a
> macro as follows:
> 	#define CNTL(c) ('c' & 037)
> While this work fine with pcc, the ANSI preprocessor doesn't expand it.

How about

#define CNTL(c) ((c) & 037)

Then change all occurances of the form

       CNTL(x)

into

       CNTL('x')

(Use an AWK program to automate things, if there's a bunch of them.)
Ain't that the "right" way to do it?

henry@utzoo.uucp (Henry Spencer) (10/22/89)

In article <11354@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>Is there something wrong with you guys, or is there a problem in the copy
>of the draft proposed Standard that you have?  The index in my copy does
>have "constant expressions"...

I can't speak for Bill, but while I'm not impressed with the index in
general, it does have this entry in my draft.  I didn't bother looking
for it at all; it's been a long time since I found the index useful,
mostly because I know where things are without it.
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

diamond@csl.sony.co.jp (Norman Diamond) (10/23/89)

In article <727@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes:

[regarding ANSIfying the CTRL(c) macro]

>Flame away if you wish, just try it first.

I can't.  I don't have a validated (or even unvalidated-but-asserted)
ANSI C compiler.  Nonetheless I do finally have a copy of the proposed
standard, which in fact is a legal one.  (Thanks Steve Friedl.)

>#define	prequote(x) 'x
>#define postquote(x) x'

I do not believe that this can possibly work in ANSI C.  Consider the
following tweaks:

#define prequote(x)  'x /* is this a comment? */
#define postquote(x) x' /* is this a comment? */

>#define	CNTL(c) ((postquote(prequote(c))) & 0x1f)
>
>CNTL(c)

Now what is the character constant?  A single character?  A longer
string?  (with implementation-defined results, especially when it's
longer than the number of chars that fit in an int...)

>Bletch :-/

True, but that's not the problem at the moment.

(In case anyone missed it, the real question is, can that solution
really possibly work in ANSI C?)

-- 
Norman Diamond, Sony Corp. (diamond%ws.sony.junet@uunet.uu.net seems to work)
  Should the preceding opinions be caught or     |  James Bond asked his
  killed, the sender will disavow all knowledge  |  ATT rep for a source
  of their activities or whereabouts.            |  licence to "kill".

cpcahil@virtech.uucp (Conor P. Cahill) (10/24/89)

In article <10983@riks.csl.sony.co.jp>, diamond@csl.sony.co.jp (Norman Diamond) writes:
> In article <727@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes:
> >#define	prequote(x) 'x
> >#define postquote(x) x'
> 
> I do not believe that this can possibly work in ANSI C.  Consider the
> following tweaks:
> 
> #define prequote(x)  'x /* is this a comment? */
> #define postquote(x) x' /* is this a comment? */

But he (dave) didn't put any comments to the right of his example, so as long
as there isn't any extra white space to the right of the code, it 
*should* work (on both pre and post ANSI).

Dave gave a good (although yukie) solution to the problem.  He didn't claim
that you could do anything with his solution and have it still work.




-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (10/25/89)

In article <727@lakart.UUCP>, dg@lakart.UUCP (David Goodenough) writes:

|  MAJOR MAJOR PROBLEM - our C compiler (greenhills) likes the useages of
|  postquote and prequote in that order. Some compilers may not care, while
|  others might want them reversed. I think it depends on whether nested
|  macros are expanded from the inside out (as Greenhills does), or outside
|  in.

  I appreciate the suggestion, but, as you say, it's not portable. Worse
than that, it doesn't work on either of the ANSI-filed compilers I
tried. Because of the way the macro is called I can't trust any editor
to change the code without breaking it, so I did the globals by hand.
The true solution would be a character analogy of #arg.
-- 
bill davidsen	(davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen)
"The world is filled with fools. They blindly follow their so-called
'reason' in the face of the church and common sense. Any fool can see
that the world is flat!" - anon