-2
$\begingroup$

In the C standard, there's this:

A parameter in the replacement list, ..., is replaced by the corresponding argument after all macros contained therein have been expanded.

It's in Section 6.10.x.x, last 2 subsections vary across editions. Section name "Argument Substitution".

The way I'm interpreting "after all macros contained therein have been expanded" is simply "ah yes, arguments are evaluated before the function call itself".

But I ran a few examples on my computer:

#define s(x) h(x) #define h(x) #x #define foo 123 h(foo) 

Terminal interaction:

$ cpp fundef.c # 1 "fundef.c" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 464 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "fundef.c" 2 #123 $ cc -E fundef.c # 1 "fundef.c" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 465 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "fundef.c" 2 "foo" $ cpp --version ; cc --version Apple clang version 17.0.0 (clang-1700.0.13.3) Target: arm64-apple-darwin24.5.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin Apple clang version 17.0.0 (clang-1700.0.13.3) Target: arm64-apple-darwin24.5.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin $ 

If macros in the arguments are replaced before they're substituted, shouldn't it end up in "123"? (Otherwise, the widely-known double-glue idiom in C wouldn't exist)

What's happenning here?

$\endgroup$
4
  • 6
    $\begingroup$ The ", unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below)," that you edited out of the middle there seems pretty material. It's interesting that cpp and cc -E are giving different output, but the quotation feels actively misleading with regard to what is being asked in the rest of the question. $\endgroup$ Commented May 22 at 8:29
  • $\begingroup$ @MichaelHomer I see. C23 and C2Y has radically restructured the text (part of the reason I assume is to delete such ambiguity). I'll study and post a self-answer when I wrapped my heads around. Thanks for the hint! $\endgroup$ Commented May 22 at 8:35
  • 2
    $\begingroup$ I am not sure this is a question about language design or implementation - the question is like "which part of the spec explains this program's behaviour?", but it doesn't ask e.g. why C's designers chose this behaviour over the language you prefer, or how to write a spec which would have the different behaviour you would prefer. $\endgroup$ Commented May 25 at 11:44
  • $\begingroup$ I think it's an implementation question of "if that's the actual behavior of existing compiler, then how do I interpret the standard to produce a compatible implementation". However, its actual content would make it off-topic on all relevant sites, probably including LangDev. $\endgroup$ Commented May 25 at 12:19

2 Answers 2

1
$\begingroup$

The key thing that your are missing is the exception that you elided in that ... in your quote. The full quote is:

A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded.

In your example, you have the macro #define h(x) #x, where the parameter x is preceded by the # token, so does NOT have macros contained in the argument expanded.

$\endgroup$
0
$\begingroup$

The macro replacement section is split up into subsections for clarity.

  1. Argument replacement.

As noted by Michael in the comment (thanks again), parameters are replaced by arguments (yes, the args evaled before func call rule apply here.), but there's a condition, which paves way for the following subsections.

  1. The # operator.

A valid (what I call) stringify sub-directive is replaced with a single character string literal pp-token that contains the spelling of the preprocessing token sequence for the corresponding argument that its parameter corresponds to - Note that further argument evalutation is not mentioned here!

  1. The ## operator.

The spec specify rules with regard to the processing of (what I call) pasting sub-directive. Again, like the stringify sub-directive, relevant (sequence(s) of) token(s) are replaced by the corresponding argument’s preprocessing token sequence, no mention of further argument evaluation is made here either.

4.a. Rescanning and further replacement, 4.b. Scope of macro definitions

The spec of rescanning makes it possible to use indirection with C macros, however the rule is specified in such way that the implementation can be simple, and some overly complex indirection may not be viable.

Since the brace characters have multiple use in the phase 7 of parsing of C language, the designers elect to not burden the preprocessor to be aware of their syntax, thus the scope of macros are not block-bound.

$\endgroup$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.