Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   macro recursion (http://www.velocityreviews.com/forums/t953309-macro-recursion.html)

W Karas 10-12-2012 10:24 PM

macro recursion
 
When pre-processing this code:

#define SUM(N) (N + 1 + SUM##N)

#define SUM10 SUM(9)
#define SUM9 SUM(8)
#define SUM8 SUM(7)
#define SUM7 SUM(6)
#define SUM6 SUM(5)
#define SUM5 SUM(4)
#define SUM4 SUM(3)
#define SUM3 SUM(2)
#define SUM2 SUM(1)
#define SUM1 SUM(0)
#define SUM0 0

int sum = SUM10;

the preprocessor seems to halt as soon as it detects the indirect recursion. Why?

Lew Pitcher 10-12-2012 10:41 PM

Re: macro recursion
 
On Friday 12 October 2012 18:24, in comp.lang.c, wkaras@yahoo.com wrote:

> When pre-processing this code:
>
> #define SUM(N) (N + 1 + SUM##N)
>
> #define SUM10 SUM(9)
> #define SUM9 SUM(8)
> #define SUM8 SUM(7)
> #define SUM7 SUM(6)
> #define SUM6 SUM(5)
> #define SUM5 SUM(4)
> #define SUM4 SUM(3)
> #define SUM3 SUM(2)
> #define SUM2 SUM(1)
> #define SUM1 SUM(0)
> #define SUM0 0
>
> int sum = SUM10;
>
> the preprocessor seems to halt as soon as it detects the indirect
> recursion. Why?


I believe that this is covered in the C standard.

In C 9899:1999 (admittedly, out of date now), Section 6.10.3.4 ("Rescanning
and further replacement") paragraph 2 states
If the name of the macro being replaced is found during this scan of the
replacement list (not including the rest of the source file’s preprocessing
tokens), it is not replaced.
Furthermore, if any nested replacements encounter the name of the macro
being replaced, it is not replaced. These nonreplaced macro name
preprocessing tokens are no longer available for further replacement even
if they are later (re)examined in contexts in which that macro name
preprocessing token would otherwise have been replaced.
The later C standards should have similar wording wrt macro expansion.

The macro expansion phases would see
SUM10
and expand that to
SUM(9)
and expand that to
(9 + 1 + SUM8)
and expand that to
(9 + 1 + SUM(7))
But, this expansion clearly involves an expansion of the SUM() macro, which
has already been expanded in the previous step. And, this re-expansion of
the SUM() macro satisfies the "nested replacements" condition of 6.10.3..4

--
Lew Pitcher
"In Skills, We Trust"

James Kuyper 10-12-2012 10:59 PM

Re: macro recursion
 
On 10/12/2012 06:24 PM, W Karas wrote:
> When pre-processing this code:
>
> #define SUM(N) (N + 1 + SUM##N)
>
> #define SUM10 SUM(9)
> #define SUM9 SUM(8)
> #define SUM8 SUM(7)
> #define SUM7 SUM(6)
> #define SUM6 SUM(5)
> #define SUM5 SUM(4)
> #define SUM4 SUM(3)
> #define SUM3 SUM(2)
> #define SUM2 SUM(1)
> #define SUM1 SUM(0)
> #define SUM0 0
>
> int sum = SUM10;
>
> the preprocessor seems to halt as soon as it detects the indirect recursion. Why?


A function-like macro definition specifies a set of tokens that will
replace the thing that looks like a function call, with variable
substitution and # and ## processing.

"After all parameters in the replacement list have been substituted and
# and ## processing has taken place, ... The resulting preprocessing
token sequence is then rescanned, along with all subsequent
preprocessing tokens of the source file, for more macro names to replace.

If the name of the macro being replaced is found during this scan of the
replacement list (not including the rest of the source files
preprocessing tokens), it is not replaced. Furthermore, if any nested
replacements encounter the name of the macro being replaced, it is not
replaced. These nonreplaced macro name preprocessing tokens are no
longer available for further replacement even if they are later
(re)examined in contexts in which that macro name preprocessing token
would otherwise have been replaced." (6.10.3.4p1-2)

The Rationale explains why they decided to make such a rule:

"A problem faced by many pre-C89 preprocessors is how to use a macro
name in its expansion without suffering recursive death. The C89
Committee agreed simply to turn off the definition of a macro for the
duration of the expansion of that macro."

I've no idea whether the following kind of macro definition played any
role in their decision, but it would not work if macros were allowed to
be recursive:

header.h:
int func(double x);

caller.c:
#include "header.h"
unsigned long func_calls = 0;
#define func(x) (func_calls++,func(x))


W Karas 10-14-2012 05:56 PM

Re: macro recursion
 
Tha

On Friday, October 12, 2012 6:59:08 PM UTC-4, James Kuyper wrote:
> On 10/12/2012 06:24 PM, W Karas wrote:
>
> > When pre-processing this code:

>
> >

>
> > #define SUM(N) (N + 1 + SUM##N)

>
> >

>
> > #define SUM10 SUM(9)

>
> > #define SUM9 SUM(8)

>
> > #define SUM8 SUM(7)

>
> > #define SUM7 SUM(6)

>
> > #define SUM6 SUM(5)

>
> > #define SUM5 SUM(4)

>
> > #define SUM4 SUM(3)

>
> > #define SUM3 SUM(2)

>
> > #define SUM2 SUM(1)

>
> > #define SUM1 SUM(0)

>
> > #define SUM0 0

>
> >

>
> > int sum = SUM10;

>
> >

>
> > the preprocessor seems to halt as soon as it detects the indirect recursion. Why?

>
>
>
> A function-like macro definition specifies a set of tokens that will
>
> replace the thing that looks like a function call, with variable
>
> substitution and # and ## processing.
>
>
>
> "After all parameters in the replacement list have been substituted and
>
> # and ## processing has taken place, ... The resulting preprocessing
>
> token sequence is then rescanned, along with all subsequent
>
> preprocessing tokens of the source file, for more macro names to replace.
>
>
>
> If the name of the macro being replaced is found during this scan of the
>
> replacement list (not including the rest of the source file�s
>
> preprocessing tokens), it is not replaced. Furthermore, if any nested
>
> replacements encounter the name of the macro being replaced, it is not
>
> replaced. These nonreplaced macro name preprocessing tokens are no
>
> longer available for further replacement even if they are later
>
> (re)examined in contexts in which that macro name preprocessing token
>
> would otherwise have been replaced." (6.10.3.4p1-2)
>
>
>
> The Rationale explains why they decided to make such a rule:
>
>
>
> "A problem faced by many pre-C89 preprocessors is how to use a macro
>
> name in its expansion without suffering �recursive death.� The C89
>
> Committee agreed simply to turn off the definition of a macro for the
>
> duration of the expansion of that macro."
>
>
>
> I've no idea whether the following kind of macro definition played any
>
> role in their decision, but it would not work if macros were allowed to
>
> be recursive:
>
>
>
> header.h:
>
> int func(double x);
>
>
>
> caller.c:
>
> #include "header.h"
>
> unsigned long func_calls = 0;
>
> #define func(x) (func_calls++,func(x))


Thank you (both) for finding the relevant citations in the Standard.

Compilers are not required to detect run-time infinite recursion, even in limited cases. Even if macro recursion were allowed, infinite macro recursion would still cause an "out of memory" compilation failure, and could be accompanied by a warning that macro recursion occurred. So banning macro recursion seems like swatting the mosquito while bleeding from the jugular.

I would guess this rule was put in place before the addition of token concatenation, on the grounds that all recursion is infinite without a conditional. Seems high time the rule was revisited.

My example is of course trivial. This issue came up for me in some (proprietary) code where the macro corresponding to SUM is several line long, so the reduction is verbosity would have been significant. I further point outthat what I'm doing here is somewhat analogous to partial template specialization in C++, a feature with well-demonstrated usefulness.

James Kuyper 10-15-2012 12:04 AM

Re: macro recursion
 
On 10/14/2012 01:56 PM, W Karas wrote:
....
> Compilers are not required to detect run-time infinite recursion,
> even in limited cases. Even if macro recursion were allowed,
> infinite macro recursion would still cause an "out of memory"
> compilation failure, and could be accompanied by a warning that macro
> recursion occurred. So banning macro recursion seems like swatting
> the mosquito while bleeding from the jugular.
>
> I would guess this rule was put in place before the addition of token
> concatenation, on the grounds that all recursion is infinite without
> a conditional. Seems high time the rule was revisited.
>
> My example is of course trivial. This issue came up for me in some
> (proprietary) code where the macro corresponding to SUM is several
> line long, so the reduction is verbosity would have been significant.
> I further point out that what I'm doing here is somewhat analogous to
> partial template specialization in C++, a feature with
> well-demonstrated usefulness.


The C99 Rationale says "The consensus of the C89 Committee is that
preprocessing should be simple and overt, that it should sacrifice power
for clarity." I think you're trying to make of the preprocessor a more
powerful device than the committee ever intended it to be. The macro
your trying to use is probably pushing the limits of what macros were
intended to be good for.
--
James Kuyper

W Karas 10-15-2012 02:00 AM

Re: macro recursion
 
On Sunday, October 14, 2012 8:04:07 PM UTC-4, James Kuyper wrote:
> On 10/14/2012 01:56 PM, W Karas wrote:
>
> ...
>
> > Compilers are not required to detect run-time infinite recursion,

>
> > even in limited cases. Even if macro recursion were allowed,

>
> > infinite macro recursion would still cause an "out of memory"

>
> > compilation failure, and could be accompanied by a warning that macro

>
> > recursion occurred. So banning macro recursion seems like swatting

>
> > the mosquito while bleeding from the jugular.

>
> >

>
> > I would guess this rule was put in place before the addition of token

>
> > concatenation, on the grounds that all recursion is infinite without

>
> > a conditional. Seems high time the rule was revisited.

>
> >

>
> > My example is of course trivial. This issue came up for me in some

>
> > (proprietary) code where the macro corresponding to SUM is several

>
> > line long, so the reduction is verbosity would have been significant.

>
> > I further point out that what I'm doing here is somewhat analogous to

>
> > partial template specialization in C++, a feature with

>
> > well-demonstrated usefulness.

>
>
>
> The C99 Rationale says "The consensus of the C89 Committee is that
>
> preprocessing should be simple and overt, that it should sacrifice power
>
> for clarity." I think you're trying to make of the preprocessor a more
>
> powerful device than the committee ever intended it to be. The macro
>
> your trying to use is probably pushing the limits of what macros were
>
> intended to be good for.
>
> --
>
> James Kuyper


Blocking recursion requires an extra rule, a special case. This is a case of reducing both clarity and power, not trading off power for clarity.

Eric Sosman 10-15-2012 02:38 AM

Re: macro recursion
 
On 10/14/2012 10:00 PM, W Karas wrote:
>[...]
> Blocking recursion requires an extra rule, a special case. This is a case of reducing both clarity and power, not trading off power for clarity.


If you don't like C, don't use it. If you want to use C,
use it as it's defined. If you don't like C as it's defined,
submit a formal change proposal to ISO. But don't just sit
there whining; it's both irritating and useless.

--
Eric Sosman
esosman@comcast-dot-net.invalid

W Karas 10-15-2012 03:01 AM

Re: macro recursion
 
On Sunday, October 14, 2012 10:38:03 PM UTC-4, Eric Sosman wrote:
> On 10/14/2012 10:00 PM, W Karas wrote:
>
> >[...]

>
> > Blocking recursion requires an extra rule, a special case. This is a case of reducing both clarity and power, not trading off power for clarity.

>
>
>
> If you don't like C, don't use it. If you want to use C,
>
> use it as it's defined. If you don't like C as it's defined,
>
> submit a formal change proposal to ISO. But don't just sit
>
> there whining; it's both irritating and useless.
>
>
>
> --
>
> Eric Sosman
>
> esosman@...


You can't tell if I'm actually whining over the Internet. Also, I could be typing standing up, like Donald Rumsfeld.

I'm sure the ISO C committee would not want to consider proposals that had not been heavily discussed in forums such as these first. Sorry if that bugs you.

Kaz Kylheku 10-15-2012 06:25 AM

Re: macro recursion
 
On 2012-10-15, W Karas <wkaras@yahoo.com> wrote:
> Blocking recursion requires an extra rule, a special case. This is a case of
> reducing both clarity and power, not trading off power for clarity.


Ah, but that the preprocessor can suffer unbounded recursion and crash is an
grave problem which *had* to be addressed.

Whereas that C programs themselves can suffer from unbounded recursion and
crash is of no consequence.

Kaz Kylheku 10-15-2012 06:26 AM

Re: macro recursion
 
On 2012-10-15, W Karas <wkaras@yahoo.com> wrote:
> I'm sure the ISO C committee would not want to consider proposals that had
> not been heavily discussed in forums such as these first. Sorry if that bugs
> you.


That evidently seems to be the benchmark for getting a new feature in.


All times are GMT. The time now is 04:55 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.