macros

K

Keith Thompson

CBFalconer said:
Keith said:
... snip ...
The preprocessor is often -- and incorrectly -- said to operate
on the text of the program's source code. In fact, it operates
on tokens (formally, "preprocessing tokens") that have been
derived from the text. These tokens simply come one after
another, pretty maids all in a row; they do not need to be
separated by spaces. Equally, though, they do not magically
combine with each other just because they happen to be adjacent.
[...]

Quite correct.

This sounds as if you are agreeing, which I trust is not so. The
point is that the tokens may be alphabetical (or numeric) strings,
and need to remain separated. For example:

#define foo((a), (b)) (a) (b)
....
foo(sizeof, char) ---> sizeof char
or ...> sizeofchar

which have much different meanings.

Yes, I agree with Eric. The preprocessor's output is a stream of
tokens; the standard says nothing about how those tokens are
represented. If the output is text to be interpreted as C source,
then certain tokens do need to be separated by whitespace so they'll
be interpreted as separate tokens. If the output is in some binary
form, or if the interface to the preprocess is a get_next_token()
function, then there is no such separation is necessary (and it may
not be meaningful).
 
K

Keith Thompson

CBFalconer said:
Your compiler is broken. What is it?

We can't be sure the compiler is broken unless we see an example where
the preprocessor misbehaves in a way that either (a) causes a legal
program to be rejected, (b) changes the semantics of a legal program,
or (c) prevents a syntax error or constraint violation from being
diagnosed. If the preprocessor's input is illegal, and its output is
illegal but in a different way, that's not necessarily a bug.
 
K

Kenneth Brody

Keith said:
CBFalconer said:
Kenneth said:
(e-mail address removed) wrote:
Can anyone explain why the output of the following code:

#define A 1
#define B 2
A.B [...]
Strange... My compiler's preprocessor outputs "1.B". (No spaces,
but it failed to expand "B".) Is it broken?

Your compiler is broken. What is it?

We can't be sure the compiler is broken unless we see an example where
the preprocessor misbehaves in a way that either (a) causes a legal
program to be rejected, (b) changes the semantics of a legal program,
or (c) prevents a syntax error or constraint violation from being
diagnosed. If the preprocessor's input is illegal, and its output is
illegal but in a different way, that's not necessarily a bug.

This program fails to compile:

==========
#define A 1
#define B 2
#define MYNUM A.B

float foo(void)
{
return MYNUM;
}

float bar(void)
{
return A.B;
}
==========

foo() compiles just fine, returning the float value 1.2, whereas
bar() fails to compile, with:

syntax error : 'constant'

on the "return A.B" line. (Asking the compiler to show the output
of the preprocessor shows that MYNUM expands to "1.2", whereas "A.B"
expands to "1.B".)

Is this one of those cases where you need an extra layer of macro,
like you do with stringifying things?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

Chris Torek

This program fails to compile:

==========
#define A 1
#define B 2
#define MYNUM A.B

float foo(void)
{
return MYNUM;
}

float bar(void)
{
return A.B;
}
==========

It should, in fact, fail to compile -- or more precisely, it must
"draw a diagnostic", after which pretty much anything can happen.
The problem is (and here "tokens" are represented by surrounding
them with angle brackets, <like> <so>) that the required token-stream
after the preprocessing phases of compilation are complete, when
the normal syntax and semantic rules of C take over, begins with:

<float> <foo> <(> <void>
<)> <{> <return> <1>
<.> <2> <;> <}>

In other words, the thing after "return" is not <1.2>-the-number,
but rather the three separate tokens <1>, <.>, and <2>, which
attempts to apply the "." operator to the number 1 and the
(not-)member-name 2.

Equivalently, you might as well have written:

return 1 . 2;

or even:

return 1/**/./**/2;

The latter used to work in the 1980s, in pre-ANSI K&R compilers --
but only in some of them, not all: some actually obeyed what K&R
said about the language in the original White Book.
foo() compiles just fine, returning the float value 1.2, whereas
bar() fails to compile, with:

syntax error : 'constant'

on the "return A.B" line.

This suggests (but does not prove) that the compiler can be shown
to be incorrect by removing function bar(), after which the one
required diagnostic will not occur.
Is this one of those cases where you need an extra layer of macro,
like you do with stringifying things?

If you want to use A.B to make MYNUM to expand to the token <1.2>,
yes -- you would have to apply the token-pasting "##" operator:

#define A 1
#define B 2
#define PASTE_DOT(x, y) x ## . ## y
#define PASTE_EXPAND_DOT(x, y) PASTE_DOT(x, y)
#define MYNUM PASTE_EXPAND_DOT(A, B)

will do the trick.
 
K

Kenneth Brody

Chris Torek wrote:
[...]
It should, in fact, fail to compile -- or more precisely, it must
"draw a diagnostic", after which pretty much anything can happen.
The problem is (and here "tokens" are represented by surrounding
them with angle brackets, <like> <so>) that the required token-stream
after the preprocessing phases of compilation are complete, when
the normal syntax and semantic rules of C take over, begins with:

<float> <foo> <(> <void>
<)> <{> <return> <1>
<.> <2> <;> <}>
[...]

Okay, I understand the subtle distinction.

The question now becomes:

Is it valid to interpret the input sequence:

return A.B;

as:

<return> <1> <.> <B> <;>

instead of:

<return> <1> <.> <2> <;>

While neither <1><.><2> nor <1><.><B> is valid here, is the compiler
allowed to not expand B?

Note that, at this point, it's acedemic, as I don't believe I've ever
used such a construct on numeric literals, and I'm just curious about
this particular aspect of this particular compiler. (Did they really
include a "this is not valid, so I don't need to continue expanding
the macro" feature into the preprocessor?)

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

Chris Thomasson

[...]
Note that, at this point, it's acedemic, as I don't believe I've ever
used such a construct on numeric literals, and I'm just curious about
this particular aspect of this particular compiler. (Did they really
include a "this is not valid, so I don't need to continue expanding
the macro" feature into the preprocessor?)

Well, the pre-processor expands some crazy stuff:

http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/89382dc9a40439c7

Like I said... Crazy!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top