[comp.std.c] Macro substitution in character literals

mbj@natasha.mach.cs.cmu.edu (Michael Jones) (12/07/90)

How can I write a macro which produces a character literal containing a macro
parameter?  I'd like to be able to write something like:
	#define chr(c) 'c'	/* Yes, this is incorrect */
which for
	chr(z)
produces
	'z'	

To do this for strings, I know I can write:

	#define str(s) # s

Is there an equivalent for character literals?

mbj@natasha.mach.cs.cmu.edu (Michael Jones) (12/08/90)

In article <11323@pt.cs.cmu.edu>, mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:
| How can I write a macro which produces a character literal containing a macro
| parameter?  I'd like to be able to write something like:
| 	#define chr(c) 'c'	/* Yes, this is incorrect */
| which for
| 	chr(z)
| produces
| 	'z'	
| 
| To do this for strings, I know I can write:
| 
| 	#define str(s) # s
| 
| Is there an equivalent for character literals?

Oh, I should add that I'd like the result to be potentially usable as a value
in compile-time initialization expressions.  Thus, I don't think the
definition:
	#define chr(c) (# s)[0]
will do in contexts such as:
	static int foo = chr(z);

gwyn@smoke.brl.mil (Doug Gwyn) (12/08/90)

In article <11323@pt.cs.cmu.edu> mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:
>Is there an equivalent for character literals?

There is no analogous "charize" operator.  It was deemed to be significantly
less useful than "stringizing", and did not have enough supporters to make
it into the standard.

About the only place I've seen an attempt at charizing is in a CTRL(c) macro
in some Berkeley code.  They were told not to do that long ago, but didn't
listen.  (CTRL('z') would have been a better design than CTRL(z).)

If you're desperate, you might try
	#define chr(c) #c[0]

sef@kithrup.COM (Sean Eric Fagan) (12/08/90)

In article <14683@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>If you're desperate, you might try
>	#define chr(c) #c[0]

Microsoft C 6.0 has a #@ construct, which is like stringizing, only it
yields a character instead of a string.

I know, it's not standard, but it is upwardly compatable with the standard,
and they might try to press for it for the next version of the standard.

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.

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

In article <1990Dec08.014241.435@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>Microsoft C 6.0 has a #@ construct [for charizing a macro argument].
>I know, it's not standard, but it is upwardly compatable with the standard,
>and they might try to press for it for the next version of the standard.

Since `@' is not part of the required character set, such a change would
require either a new trigraph, or an admission that trigraphs were never
necessary in the first place.

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

henry@zoo.toronto.edu (Henry Spencer) (12/11/90)

In article <11327@pt.cs.cmu.edu> mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:
>| How can I write a macro which produces a character literal containing a macro
>| parameter?  I'd like to be able to write something like:
>| 	#define chr(c) 'c'	/* Yes, this is incorrect */
>Oh, I should add that I'd like the result to be potentially usable as a value
>in compile-time initialization expressions...

Can't be done.
-- 
"The average pointer, statistically,    |Henry Spencer at U of Toronto Zoology
points somewhere in X." -Hugh Redelmeier| henry@zoo.toronto.edu   utzoo!henry

diamond@tkou02.enet.dec.com ("diamond@tkovoa") (12/11/90)

In article <14683@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <11323@pt.cs.cmu.edu> mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:
>>Is there an equivalent for character literals?
>There is no analogous "charize" operator.
(True, of course.)
 
>It was deemed to be significantly
>less useful than "stringizing", and did not have enough supporters to make
>it into the standard.
 
You mean it was not an oversight, that it was deliberate?
Well, we certainly see evidence over and over again on the net.
"The reports of our non-existence are greatly exaggerated."
 
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

james@bksmel.oz.au (James Crawford) (12/12/90)

In article <1990Dec10.173255.805@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
> In article <11327@pt.cs.cmu.edu> mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:
>>| How can I write a macro which produces a character literal containing a macro
>>| parameter?  I'd like to be able to write something like:
>>| 	#define chr(c) 'c'	/* Yes, this is incorrect */
>>Oh, I should add that I'd like the result to be potentially usable as a value
>>in compile-time initialization expressions...
>
> Can't be done.
> -- 
> "The average pointer, statistically,    |Henry Spencer at U of Toronto Zoology
> points somewhere in X." -Hugh Redelmeier| henry@zoo.toronto.edu   utzoo!henry

I seem to have started in the middle of this discussion and I am not sure what
this is doing in comp.std.c but heres my $0.02 worth...

I think for ANSI C compilers you should be able to get around this with
token pasteing.

On K&R compilers try the following:

#define QUOTE() '
#define QUOTE_CHR(C) QUOTE()C

#define chr(C) QUOTE_CHR(C)'

This seems to produce the desired effect.

flaps@dgp.toronto.edu (Alan J Rosenthal) (12/12/90)

>In article <14683@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>>There is no analogous "charize" operator.
>>It was deemed to be significantly
>>less useful than "stringizing", and did not have enough supporters to make
>>it into the standard.

diamond@tkou02.enet.dec.com ("diamond@tkovoa") writes:
>You mean it was not an oversight, that it was deliberate?
>Well, we certainly see evidence over and over again on the net.

We've certainly seen no reason to write the macro so that it is called like
CTRL(d) rather than CTRL('d').

And the request to be able to write chr(c) rather than 'c' shows an
unfamiliarity or uncomfortableness with C, just like people who #define NL '\n'
(or even worse, define it as 10).

ajr

henry@zoo.toronto.edu (Henry Spencer) (12/13/90)

In article <362@bksmel.oz.au> james@bksmel.UUCP (James Crawford) writes:
>>>| ... I'd like to be able to write something like:
>>>| 	#define chr(c) 'c'	/* Yes, this is incorrect */
>>>... I'd like the result to be potentially usable as a value
>>>in compile-time initialization expressions...
>>
>> Can't be done.
>
>I think for ANSI C compilers you should be able to get around this with
>token pasteing.

Nope.  Token pasting pastes *tokens* together.  An isolated single quote
may or may not be a valid preprocessor token -- ANSI C behavior is
explicitly undefined when you try to treat ' or " as a pp-token.
-- 
"The average pointer, statistically,    |Henry Spencer at U of Toronto Zoology
points somewhere in X." -Hugh Redelmeier| henry@zoo.toronto.edu   utzoo!henry

david@lpi.liant.com (David Michaels) (12/15/90)

In article <11323@pt.cs.cmu.edu>
mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:

> How can I write a macro which produces a character literal containing a macro
> parameter?  I'd like to be able to write something like:
>	#define chr(c) 'c'	/* Yes, this is incorrect */
> which for
>	chr(z)
> produces
>	'z'	

ANSI C does not support any way do this, although many older
Classic C compilers (particularly PCC-based compilers) supported
it (as well as macro parameter substitution within string literals).
It should be avoided if at all possible.

LPI's ANSI C compiler (NEW C) has a Classic C option "-xc" which will cause
macro parameter substitution within character constants to be performed.
Another option "-xwc" will cause warnings to be given wherever a function-
like macro is defined such that macro parameter substitution within character
constants *could* take place.  Both of these options may be given at once.

There are also exactly analogous options "-xs" and "-xws" for macro
parameter substitutions within string literals (although there is of
course an ANSI C way to deal with this, i.e the stringize "#" operator).

				-- David Michaels (david@lpi.liant.com)
				   Language Processors, Inc.
				   959 Concord Street
				   Framingham, MA 01701-4613
				   (508) 626-0006

thorinn@rimfaxe.diku.dk (Lars Henrik Mathiesen) (12/22/90)

david@lpi.liant.com (David Michaels) writes:
>mbj@natasha.mach.cs.cmu.edu (Michael Jones) writes:
>> How can I write a macro which produces a character literal containing
>> a macro parameter?  I'd like to be able to write something like:
>>	#define chr(c) 'c'	/* Yes, this is incorrect */
>> which for
>>	chr(z)
>> produces
>>	'z'	

>ANSI C does not support any way do this, ...

More precisely, there is no way a strictly conforming program can do
this. As far as I can tell, a conforming implementation can allow
something like this:

	#define _chr(x,q) q##x##q
	#define chr(x) _chr(x,')

It has to be an implementation that treats an unmatched single-quote
as a preprocessing token by itself (the behaviour is undefined, see
section 3.1). Likewise, it must allow malformed tokens as intermediate
results during token pasting (undefined by 3.8.3.3). In such an
implementation, the code shown does not violate any constraints or
syntax rules. (The constraint in 3.1 talks about the lexical form of
preprocessing tokens converted in translation phase 7, not of their
derivation.)

But I don't think that such an implementation will become common. It
mucks up the scanner (which has to rescan the part of the line after
the unmatched quote), and it conflicts with the GNU C extension of
allowing newlines in character-constants and string-literals.

--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark      [uunet!]mcsun!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.      thorinn@diku.dk