macros

S

Silent Witness

Hi

Can anyone explain why the output of the following code:

#define A 1
#define B 2
A.B

after preprocessing only, is:

1 . 2

Why does the preprocessor put spaces between each character, when the
macro invocation has none?
 
R

Richard Tobin

Silent Witness said:
Can anyone explain why the output of the following code:

#define A 1
#define B 2
A.B

after preprocessing only, is:

1 . 2

Why does the preprocessor put spaces between each character, when the
macro invocation has none?

C preprocessing is not defined as a textual transformation, but as a
transformation between sequences of tokens. There's no need for a C
compiler to be able to output the result of preprocessing as text - it
can just produce some internal representation suitable for the next
stage of compilation.

Of course, it's traditional for the preprocessor to be usable by
itself, and to ensure that the textual representation corresponds
to the correct sequence of tokens it's putting spaces between them.

If you want to combine two tokens into one, you need to use "token
pasting" (Google for it).

-- Richard
 
?

=?iso-2022-kr?q?Harald_van_D=0E=29=26=0Fk?=

Hi

Can anyone explain why the output of the following code:

#define A 1
#define B 2
A.B

after preprocessing only, is:

1 . 2

Why does the preprocessor put spaces between each character, when the
macro invocation has none?

Probably to make sure that it won't be interpreted as a single floating-
point number after preprocessing. It is an integer constant, followed by
a period, followed by another integer constant, and the compiler has to
make sure it is interpreted as that. It may do so using whitespace, and
in your case does. Anyway, standard C does not require preprocessor
output to be available at all except when stringizing:

#define A 1
#define B 2
#define STR(x) STR_(x)
#define STR_(x) #x

#include <stdio.h>
int main(void) {
puts(STR(A.B));
return 0;
}

If your implementation prints "1 . 2\n" in this case too, then it is a
bug. However, I would expect it will print "1.2\n" here.
 
C

CBFalconer

Silent said:
Can anyone explain why the output of the following code:

#define A 1
#define B 2
A.B

after preprocessing only, is:

1 . 2

Why does the preprocessor put spaces between each character, when
the macro invocation has none?

Because A is a token, B is a token, and '.' is a token. What if:

#define A sizeof
#define B stdin

do you want A B translated as "sizeofstdin" or "sizeof stdin"?
Injection of spaces preserves the 'tokenness' of the individual
items.
 
K

Kenneth Brody

CBFalconer said:
Because A is a token, B is a token, and '.' is a token. What if:
[...]

Didn't we have this exact question posted a few weeks ago? I
remember, because my compiler's preprocessor would generate "1.B"
as its output, and we had a whole discussion here as to whether
that was legal or not.

--
+-------------------------+--------------------+-----------------------+
| 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]>
 
M

Martin Wells

Chuck:
Because A is a token, B is a token, and '.' is a token. What if:

#define A sizeof
#define B stdin

do you want A B translated as "sizeofstdin" or "sizeof stdin"?
Injection of spaces preserves the 'tokenness' of the individual
items.


I don't see your point. If you write "A B", then obviously you already
have a space and it should be "sizeof stdin". As for "A.B", well
that's a different kettle of fish altogether.

I myself wuda thought that you'd be left with "sizeof.stdin" as
opposed to "sizeof . stdin"... but then I don't know the intracies at
play here.

Martin
 
C

CBFalconer

Martin said:
Chuck:


I don't see your point. If you write "A B", then obviously you
already have a space and it should be "sizeof stdin". As for "A.B",
well that's a different kettle of fish altogether.

I myself wuda thought that you'd be left with "sizeof.stdin" as
opposed to "sizeof . stdin"... but then I don't know the intracies
at play here.

No you don't "have a space". Spaces, in C, are to be ignored,
EXCEPT that they serve to delimit the edges of tokens. The C
preprocessor handles only text, so it has to inject spaces to keep
tokens separate. It absorbs the token A, looks it up, and spits
out the translation, followed by a delimiting space, then absorbs
the token B, and repeats the process.
 
K

Keith Thompson

CBFalconer said:
No you don't "have a space". Spaces, in C, are to be ignored,
EXCEPT that they serve to delimit the edges of tokens. The C
preprocessor handles only text, so it has to inject spaces to keep
tokens separate. It absorbs the token A, looks it up, and spits
out the translation, followed by a delimiting space, then absorbs
the token B, and repeats the process.

The output of the preprocessor is a sequence of tokens. It isn't
necessarily text.

A typical *implementation* emits text that looks very much like C
code; such an implementation will sometimes need to emit spaces to
separate adjacent tokens. But that's just an internal implementation
detail.
 
K

Kenneth Brody

Keith said:
The output of the preprocessor is a sequence of tokens. It isn't
necessarily text.

A typical *implementation* emits text that looks very much like C
code; such an implementation will sometimes need to emit spaces to
separate adjacent tokens. But that's just an internal implementation
detail.

And, in fact, getting back to the OP...

=====
#define A 1
#define B 2

whatever A.B whatever
=====

If the preprocessor were to emit a text file consisting of:

whatever 1.2 whatever

and then pass that file on to the compiler, it would change the
meaning of "A.B". Because "A.B" expands to three tokens, "1", ".",
and "2", and "1.2" is a single token, the two are not equivalent.
In order to preserver the "these are separate tokens", it must
create the text file[1] with the spaces.

Note, too, that "structure . member" is just as valid (at least
according to my compiler, with all warnings turned to max) as
"structure.member".


[1] Note that "must create the text file" is taken in the context
of the preprocessor creating a file to pass to the compiler.
Obviously, nothing requires that it actually do so, and could
instead pass the token stream to a compiler without the use of
an external file.

--
+-------------------------+--------------------+-----------------------+
| 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]>
 

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

macros 25
Endianness macros 48
Macros 16
macros that build macros 6
macros again 1
standard functions as macros 7
Macros accepting structs as input argument 6
How to position the *tooltip* comment on these buttons? 9

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top