Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Sort char array Date: Fri, 08 Nov 2019 22:03:51 -0800 Organization: A noiseless patient Spider Lines: 237 Message-ID: <8636exegc8.fsf@linuxsc.com> References: <87mue8fx7b.fsf@bsb.me.uk> <1QInF.797536$aq7.506537@fx09.am4> <875zkwf27e.fsf@bsb.me.uk> <87a7a66eyk.fsf@bsb.me.uk> <6%ioF.849405$893.123190@fx02.am4> <20191014013916.333bfd71e8363156058a1b2e@gmail.com> <86imor73wp.fsf@linuxsc.com> <20191015002630.213bbd842f2f5aa17c73015d@gmail.com> <8636fs6adz.fsf@linuxsc.com> <20191019003905.826b918468a4ab42279e0ea4@gmail.com> <86v9skhotz.fsf@linuxsc.com> <20191108183821.6f16f39f6a377a873006fa01@g{oogle}mail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="bd07fdb0e7610947dc98257bdadc7724"; logging-data="20350"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18JqWqa7LynB1RlNbuLSwJp9+p2mODmVIw=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:sEaKE6/sl1A21/FXP7kuIAptkS0= sha1:FQmz0wrtZRBVkn6tf6oWOxLpSSA= Xref: csiph.com comp.lang.c:147814 Anton Shepelev writes: > Tim Rentsch to Anton Shepelev: > >>> #define FID( F ) FID1(PREF, F) >>> #define FID1(P,F) FID2( P, F) >>> #define FID2(P,F) P ## F >>> >>> After reading about that in the standard, I still do not >>> understand why my solution requires both FID1 and FID2 >>> to expand PREF. As far as I have understood the >>> starndard, PREF should be expanded during the rescan >>> stage of FID expansion, but it is not. Why? >> >> We start with a call to the FID() macro: >> >> ^ FID( some_name ) ... >> >> The ^ indicates the scan arrow, the ... indicates the rest >> of the file. Assuming the argument 'some_name' is already >> fully expanded, the first level of expansion gives this: >> >> ^ FID1( PREF, some_name ) ... >> >> In expanding this macro call, the argument PREF is >> expanded before being substituted for P in the definition >> 'FID2( P, F )', > > I fear it contradicts 6.10.3.1, which you quote below. The > paragraph says that expansion of the arguments takes place > *after* substution of them into the macro body (aka > replacement list). That said, PREF is first subsituted into > the defintion and then expanded: > > FID2( PREF, some_name ) > FID2( MyPrefix_, some_name ) > > Right? I think you are misreading what the paragraph says. First here is the whole paragraph of 6.10.3.1 p1, completely verbatim: After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. 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. Before being substituted, each argument's preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available. Here is a summary, with my emphasis: [...] A parameter in the replacement list, unless [some cases that don't apply here], is replaced by the corresponding argument AFTER ALL MACROS CONTAINED THEREIN HAVE BEEN EXPANDED. BEFORE BEING SUBSTITUTED, each argument's preprocessing tokens ARE COMPLETELY MACRO REPLACED as if they formed the rest of the preprocessing file; no other preprocessing tokens are available. Parameter replacement by its argument happens AFTER that argument has been macro expanded. The second sentence emphasizes this: each argument's preprocessing tokens are completely macro replaced BEFORE being substituted for the parameter. Expansion of the argument happens first; substituting the expanded argument for (each occurrence of) the corresponding parameter happens second. Maybe what's confusing you is that there are /two/ substitutions. First (expanded) arguments are substituted for parameters in the definition. Second the resulting sequence of tokens is substituted back in place of the original (and now deleted) macro call. The sequence of actions is one: expand arguments two: substitute arguments for parameters three: do any stringizing or token pasting needed four: substitute the resulting token sequence in place of the original macro call five: continue scanning with the token sequence just substituted >> so we get >> >> ^ FID2( MyPrefix_, some_name ) ... >> >> which upon one expansion gives >> >> ^ MyPrefix_some_name ... >> >> at which point, assuming 'MyPrefix_some_name' is not >> defined as a macro, leads to >> >> MyPrefix_some_name ^ ... >> >> which is what we want. > > Ok. > >> Now suppose the FID() macro had used FID2() rather than >> FID1(). Then the first level of expanding >> FID( some_name ) gives this: >> >> ^ FID2( PREF, some_name ) ... > > I think PREF is not expanded here because it is not a > argument to FID() and therefore not subject to 6.10.3.1. I don't know why you think that. The call to FID() has been processed, leaving the expansion text 'FID2( PREF, some_name )' to be rescanned. The first argument to the FID2() call is the token PREF; that argument is treated as a macro argument under the rules of 6.10.3.1 p1. The expansion of FID has been substituted and is in the process of being rescanned. There is a macro call to FID2 in the subsituted expansion, and it is treated just the same as though the macro call were occurring at the top level. (I feel obliged to point out that there is an exception to what I said in the last sentence, but it has no bearing on what we are talking about in this discussion.) In this case the argument PREF is not expanded before being subsituted for the parameter P because P is immediately followed by a ## operator. A parameter being followed by a ## operator prevents the expansion of its argument /for that occurrence of the parameter/. An easy way to see what's going on is this: #define FOO BAS #define AB(X) { X, #X } AB(FOO) Running this through gcc -E gives # 1 "" # 1 "" # 1 "" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "" 2 # 1 "" { BAS, "FOO" } The argument FOO is expanded for the _first_ occurrence of X, because it has no # in front of it, but is /not/ expanded for the _second_ occurrence of X, because that occurrence of the parameter X /does/ have a # in front of it. The situation with the ## token-pasting operator is similar. >> At this point we need to replace a call to FID2(), which >> is defined as >> >> #define FID2(P,F) P ## F >> >> The first argument, PREF, is substituted for P in the >> definition. But how is it substituted? The specification >> for that is given in section 6.10.3.1. Paragraph 1 of >> that section starts >> >> After the arguments for the invocation of a function- >> like macro have been identified, argument substitution >> takes place. 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. > > I see: the preprocessor identifies the argument PREF but > does not expand it. Thanks! > >> We can test this theory by defining PREFsome_name: >> >> #define PREFsome_name HOLY_SMOKES >> #define PREF MYPrefix_ >> >> #define FID( F ) FID2(PREF, F) >> #define FID2(P,F) P ## F >> >> FID( some_name ) > > My understaning: > > 1. FID( some_name ) > 2. FID2( PREF, some_name ) > (PREF not expanded because not an argument to FID) > 3. PREF ## somename > 4. PREFsome_name > (PREF and some_name not expanded becase of ##) > 5. HOLY_SMOKES > > Do you agree? No, I disagree on item 2. The call to FID2 is right, but the argument PREF is not expanded because of how FID2 is defined. In particular, the only occurrence of the parameter P in the definition of FID2 is immediately followed by a ## operator, which prevents expanding the argument. Also, what you say in item 4 is not quite right. It is true that PREF and some_name aren't expanded before being token-pasted, but there is no opportunity for them to /be/ expanded. The definition of FID2 is #define FID2(P,F) P ## F so when the call FID2( PREF, some_name ) is seen, we first get an expanded macro body PREF ## some_name which token pastes to PREFsome_name but this happens /before/ the resulting sequence of tokens is substituted back in place of the call to FID2. It is only /after/ that substitution occurs that the generated text is re-scanned looking for further macro calls. To say this another way, there is never an opportunity for the sequence PREF ## some_name to be macro-expanded before the token pasting to PREFsome_name occurs. Does this all make sense? I know it can be confusing.