What is the output of the following code?

A

asdfghjk

Can somebody explain the output?

#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int main()
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}
 
I

Ian Collins

#include<stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int main()
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}

It's quite simple, what do think ?
 
E

Eric Sosman

Can somebody explain the output?

Yes. In fact, anyone who has paid careful attention to
section 6.10.3 of the Standard can explain it. Even people like
me whose study of 6.10.3 has been only cursory are able to
explain the output, because they (we, I) know how to find the
relevant parts of the Standard at need.

More to the point, though, people with a grain of sense
(whether they've internalized 6.10.3 or not) will refrain from
code like this, and if they encounter it in reviews of someone
else's code they're likely to suggest it be rewritten (often
accompanying the suggestion with the casual display of a set of
brass knuckles or similar instruments of persuasion). This sort
of stuff belongs in obfuscation contests and interview gotchas.
[... macro silliness snipped ...]

By the way, I have no objection to macro magic *in a good cause*,
and I have no patience with silly dicta like "Thou shalt not abuse
the syntax." But you've got to convince me of the goodness of the
cause, and you've got to justify the abuses; if you can't do one or
the other -- well, gosh, it's a good thing I didn't try to take
*this* through airport security, isn't it? Wanna see how it works?
 
G

Geoff

Can somebody explain the output?

#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int main()
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}

Yes, the output is the string representation of the macros h(a) and
g(a) when given the argument macro f(a,b) where a = 1 and b = 2.
 
A

asdfghjk

I do not understand why the first printf gives 12 as output while the
second gives f(1,2). Somebody please help?
 
B

Ben Bacarisse

asdfghjk said:
I do not understand why the first printf gives 12 as output while the
second gives f(1,2). Somebody please help?

I suspect people are holding back because this looks so much like a
piece of coursework.

Why don't you post the sequence of actions as you see it happening and
then I think people will be happy to correct the details. I.e. state
what tokens are associated with what macro arguments and the exact
sequence of replacements that occurs. Doing it this way, not only will
you get your answer but you will get an exact correction for whatever
bit of the process is confusing you.

You snipped the context, so here it is again:

#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

What do you think happens to

h(f(1,2))
and
g(f(1,2))
?
 
A

Alan Curry

Why don't you post the sequence of actions as you see it happening and
then I think people will be happy to correct the details. I.e. state

I'll take it from here... but I'll answer in the form of "what would happen
if cpp wasn't completely unreasonable".
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

What do you think happens to

h(f(1,2))

If cpp wasn't completely unreasonable...

In an expression with nested parentheses, the innermost operation has the
highest precedence. So first we evaluate
f(1,2)
which yields
12

Now we have
h(12)
which becomes
g(12)
which becomes
"12"
and
g(f(1,2))

This version starts the same. Evaluate
f(1,2)
which yields
12

Now we have
g(12)
which becomes
"12"

Now if someone could supply a rationale for the *actual* behavior, using
short, simple sentences like I did for mine... I'll be surprised.
 
B

Ben Bacarisse

I'll take it from here... but I'll answer in the form of "what would happen
if cpp wasn't completely unreasonable".


If cpp wasn't completely unreasonable...

In an expression with nested parentheses, the innermost operation has the
highest precedence. So first we evaluate
f(1,2)
which yields
12

Now we have
h(12)
which becomes
g(12)
which becomes
"12"


This version starts the same. Evaluate
f(1,2)
which yields
12

Now we have
g(12)
which becomes
"12"

Now if someone could supply a rationale for the *actual* behavior, using
short, simple sentences like I did for mine... I'll be surprised.

Hmmm, you my have made up your mind already! The *actual* behaviour
allows a macro to capture a function call form:

#define DEBUG1(call) printf("%s == %d\n", #call, call)

DEBUG1(f(1, 2));

DEBUG1 works the same even when f has been overridden by a macro
definition, for example:

#define f(a, b) sin(a + b)

If you want to capture the form after expansion you can do that too:

#define XSTR(x) #x
#define DEBUG2(call) \
printf("%s (actually %s) == %d\n", #call, XSTR(call), call)

This may not be compelling enough for you, but it is a not uncommon use
case.

The behaviour is simple terms is that arguments are collected and are
expanded at the time they get interpolated into the macro body. Both
# and ## inhibits expansion of the affected tokens.
 
A

Alan Curry

Notice how I gave a sequence of steps, with a rationale for each step.

Your example, while perhaps interesting, doesn't have that.

In particular, "what's inside the most parentheses has the highest
precedence" is a simple rule that is consistent with the general use of
parentheses elsewhere. You didn't rebut it or offer an equally simple and
logical alternative; you just skipped it.
 
B

Ben Bacarisse

Notice how I gave a sequence of steps, with a rationale for each step.

Your example, while perhaps interesting, doesn't have that.

In particular, "what's inside the most parentheses has the highest
precedence" is a simple rule that is consistent with the general use of
parentheses elsewhere.

I'd put it differently because I don't like conflating precedence with
order of evaluation. I'd cite the fact that function arguments are
fully evaluated before the function is called as the "model" for inside
out macro expansion.
You didn't rebut it or offer an equally simple and
logical alternative; you just skipped it.

Yes, I did. The rebuttal is that expanding "inside out" precludes an
important use case. I gave that usage but it is true that I left out
the fact that inside out expansion makes it impossible (without
introducing a new quoting mechanism into the pre-processor). You are an
intelligent poster, and I would not presume to patronise you by spelling
it out like that.

Your rule is not enough to define the semantics of a macro processor, so
it is not fair to ask for as simple a rule that does. I could, however,
say that "C expands macros left to right" which is short and sweet and
says about as much about the real semantics as your rule does about the
putative semantics of you sane pre-processor. The rationale for this
simple rule is that permits functional forms to be quoted using #.
 
A

Alan Curry

I'd put it differently because I don't like conflating precedence with
order of evaluation. I'd cite the fact that function arguments are
fully evaluated before the function is called as the "model" for inside
out macro expansion.

Now I'm lost. Is that a rewording of my description, or is it supposed to
support the opposite behavior? I interpret it as supporting my definition,
not the "correct" one.

The problematic version is this:
#define f(a,b) a##b
#define g(a) #a
g(f(1,2))

Trying to make an analogy in proper (non-preprocessor) C, I'd write this:

char *f(char *a, char *b)
{
return strcat(strcpy(malloc(strlen(a)+strlen(b)+1), a), b);
}

char *g(char *a)
{
return strcat(strcat(strcpy(malloc(strlen(a)+3), "\""), a), "\"");
}

int main(void)
{
char *result = g(f("1","2"));
puts(result);
}

So my description of the sane preprocessor follows what normal C code does.

And this is a case where order of evaluation is determined by precedence.
There's no way you can call g until the result of f is known. Mentioning
"evaluation order" is always a good way to start a thousand-post thread
about sequence points so I tried to avoid it until now. I known order isn't
the same as precedence, in an expression like foo()+bar()*baz(). But in this
case, I don't see how you can separate them.
Yes, I did. The rebuttal is that expanding "inside out" precludes an
important use case. I gave that usage but it is true that I left out
the fact that inside out expansion makes it impossible (without
introducing a new quoting mechanism into the pre-processor). You are an
intelligent poster, and I would not presume to patronise you by spelling
it out like that.

Well I wasn't kidding; I really wouldn't mind seeing someone spell out the
rules for nested preprocessor expressions involving both "#" and "##",
because I really don't understand them. I knew my answers to "what will the
output be" were wrong, because I've got enough experience to know that cpp is
scary. I suspected that one of them would output "12" and the other would
output something silly. And I was right about that! But I didn't know which
would be which.

These dark corners of the preprocessor have been explained in one of 2 ways:

1. Useful Idiom Cookbook, with explanations of what the idioms do, but not
much detail on why. They have entries like

#define Str(x) #x
#define Xstr(x) Str(x)

I've used that one a few times. Each time I need it, I have to go find it in
one of my older projects and copy it. I can't write it from scratch. It just
doesn't make sense to me. How an Xstr and Str not do the same thing? The Xstr
definition says to me "do the same thing Str does", but to cpp it says
something else.

2. Standardese, in which every detail is given, enough to reimplement cpp
from scratch, but no rationale.

I'd like to see something in between, in which the individual steps are
actually explained in a manner that makes intuitive sense. Starting from
"these are the idioms we want to support" and working backward to generate
the rules is not helpful.
Your rule is not enough to define the semantics of a macro processor, so
it is not fair to ask for as simple a rule that does. I could, however,
say that "C expands macros left to right" which is short and sweet and
says about as much about the real semantics as your rule does about the
putative semantics of you sane pre-processor. The rationale for this
simple rule is that permits functional forms to be quoted using #.

It sounds like a good start. But since I know how yacc works, I also know
that the main C grammar is also parsed "left to right", with shift and reduce
operations. In other words, this thing I wrote above:

char *result = g(f("1","2"));

can also be parsed left to right, and the result is still that the value
returned by f() is given to g(). I can't see any other meaning it might have.
But when we convert it to the closest possible equivalent with preprocessor
macros, it changes into one of those other meanings that I can't see.
 
F

FX

Alan Curry wrote: :
If cpp wasn't completely unreasonable...

In an expression with nested parentheses, the innermost operation has the
highest precedence.

That's wrong, although this is most of the time equivalent to the real
behavior. Indeed, macros are expanded from left to right (outermost to
innermost) but their parameters are *first* substituted and expanded
*unless* # or ## operators are used on them (see 6.10.3.1 of the standard).

So the sequence of substitutions is somehow recursive. Here it is:

- Expanding macro h:
- a => f(1,2)
- Expanding macro f:
- a##b => 12
=> 12
=> g(12)
- Expanding macro g:
- #a is replaced by a string: #a => "12"
=> "12"


- Expanding macro g:
- #a => "f(1,2)"
=> "f(1,2)"

Now if someone could supply a rationale for the *actual* behavior, using
short, simple sentences like I did for mine... I'll be surprised.

I hope this helps. I don't know if my explanations are clear enough. I'm
sure this is better explained somewhere on the web.
 
B

Ben Bacarisse

Now I'm lost. Is that a rewording of my description,

Yes, just re-wording your description. Precedence does not determine
evaluation order so, for me, the best motivation to support your macro
semantics is plain old function call.

Well I wasn't kidding; I really wouldn't mind seeing someone spell out the
rules for nested preprocessor expressions involving both "#" and "##",
because I really don't understand them. I knew my answers to "what will the
output be" were wrong, because I've got enough experience to know that cpp is
scary. I suspected that one of them would output "12" and the other would
output something silly. And I was right about that! But I didn't know which
would be which.

Macros are expanded left to right. The expansion of function-like
macros involves

(1) collecting the token sequence for the arguments (respecting
parentheses that are not in string or character constants);

(2) replacing the "call" with the macro body, substituting all unquoted
parameter references with the expanded version of the token list
collected in step 1.

Both # and ## "quote" their operands. The macro expansion of the token
lists bound to a and b by step 1 is not performed when substituting #a
or a##b in step 2.

I don't think that is so very complicated (and I am sure I got some
details wrong, but that is the gist of it). Many macro processors
behave like this -- TRAC and TeX for example (though not m4 -- m4 does
what you want). Think of it, if you like, as call by name or lazy
evaluation as used in some programming languages.

The recursive expansion occurs during parameter replacement not during
parameter collection. That's the main difference between what you
expect and what you get with C.

<snip>
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top