Correct rules for function macro parameter lists 
Author Message
 Correct rules for function macro parameter lists

Firstly, let me say I'm aware its generally not a good idea to push the
preprocessor too hard...

Whilst experimenting with the preprocessor, I found you can get up to a
little mischief with the parameter list to macro functions, as shown in
the example I've listed at the end of this message. What'd like to know is:

1. What are the rules (if any) of supplying "missing" parameters to
macro functions. (There are quite a few variations to this - I've listed
some in the code example below.)

2. Is it "legal" in the standard to have spaces between the macro
function and the first left bracket of the parameter list in macro
invocations? (As in 'exitThis (a)'.) This does parallel the rules for
parsing "real" functions, so its at least consistent. (I know you can
have spaces before the left bracket in the macro definition for obvious
reasons.)

I've looked in this list's FAQ and in C-ARM (4th Ed. - I'm not up to
date) but nothing obvious addressing this seems to be present. I have a
suspicion that the rule is "unexpected behaviour"... but it'd be useful
to know if there is some set rules in the standard(s) before I either
exploit this behaviour or try use some other means.

Only the third and last invocations of someMacro() generate a warning in
cpp when -Wall is applied: cpp seems to be happy as long as the right
number of commas are present.

Grant

The code:
-------------------------------------------------------
#define voidThing
# define exitThis(x)  return x
exitThis(a) ;
exitThis() ;
exitThis( voidThing ) ;
exitThis (a) ;

#define someMacro(x,y) thisis(x) ; thatis(y)
someMacro(a,b)
someMacro(a,)
someMacro(a)
someMacro(,b)
someMacro(,)
someMacro()
-------------------------------------------------------
generates:
-------------------------------------------------------
return a ;
return  ;
return    ;
return a ;

thisis(a) ; thatis(b)
thisis(a) ; thatis()
thisis(a) ; thatis()
thisis() ; thatis(b)
thisis() ; thatis()
thisis() ; thatis()
-------------------------------------------------------



Mon, 31 Oct 2005 10:02:55 GMT  
 Correct rules for function macro parameter lists

Quote:

> Firstly, let me say I'm aware its generally not a good idea to push the
> preprocessor too hard...

> Whilst experimenting with the preprocessor, I found you can get up to a
> little mischief with the parameter list to macro functions, as shown in
> the example I've listed at the end of this message. What'd like to know is:

> 1. What are the rules (if any) of supplying "missing" parameters to
> macro functions. (There are quite a few variations to this - I've listed
> some in the code example below.)

AFAIK, all you need is the right number of commas.  Parentheses protect
commas from the preprocessor, so

#define foo(x) bar x
foo((a,b))

produces

bar (a,b)

Quote:
> 2. Is it "legal" in the standard to have spaces between the macro
> function and the first left bracket of the parameter list in macro
> invocations? (As in 'exitThis (a)'.) This does parallel the rules for
> parsing "real" functions, so its at least consistent.

Yes.  There was some debate a while back over whether the *original* K&R
allowed this, but it's well-defined and well-known in modern C (C89, C99).

Quote:
> (I know you can
> have spaces before the left bracket in the macro definition for obvious
> reasons.)

But *only* for obvious reasons - obscure reasons require a comment. :)

#define foo (apple) bar((apple *)fruit)   /* Not a typo! */

which should anyway be re-written as

#define foo ((apple) bar((apple *)fruit))

Note that both of these #define an object-like macro 'foo', NOT a
function-like macro 'foo(apple)', and that

#define foo(apple) bar((apple *)fruit)  /* Different! */

would be drastically different in effect!

Quote:
> I've looked in this list's FAQ and in C-ARM (4th Ed. - I'm not up to
> date) but nothing obvious addressing this seems to be present. I have a
> suspicion that the rule is "unexpected behaviour"... but it'd be useful
> to know if there is some set rules in the standard(s) before I either
> exploit this behaviour or try use some other means.

UB sounds good to me.  Don't ever trust GCC or Microsoft to do the correct
thing - they, especially GCC, have extensions up the wazoo.

Quote:
> Only the third and last invocations of someMacro() generate a warning in
> cpp when -Wall is applied: cpp seems to be happy as long as the right
> number of commas are present.

Yep.

Quote:
> #define voidThing
> # define exitThis(x)  return x
> exitThis() ;

I'd expect this to be UB.

Quote:
> #define someMacro(x,y) thisis(x) ; thatis(y)
> someMacro(a)
> someMacro()

And these two.

I'd suggest checking the FAQ (just to be sure), and then going straight
to the Standard if you really need to know.  Or hang around and somebody
else may even do it for you.

HTH,
-Arthur



Mon, 31 Oct 2005 10:52:15 GMT  
 Correct rules for function macro parameter lists

Quote:

>I've looked in this list's FAQ and in C-ARM (4th Ed. - I'm not up to
>date) but nothing obvious addressing this seems to be present. I have a
>suspicion that the rule is "unexpected behaviour"... but it'd be useful
>to know if there is some set rules in the standard(s) before I either
>exploit this behaviour or try use some other means.

>UB sounds good to me.  Don't ever trust GCC or Microsoft to do the correct
>thing - they, especially GCC, have extensions up the wazoo.

Thats for sure. I've no experience with Microsoft's thing though. I read
C-ARM front to end to make sure I'd sussed most of what was standard as
opposed to gcc extras. Of course that was a while back so most of its
fading...

Quote:
>Only the third and last invocations of someMacro() generate a warning in
>cpp when -Wall is applied: cpp seems to be happy as long as the right
>number of commas are present.

>Yep.

>>#define voidThing
>># define exitThis(x)  return x
>>exitThis() ;

>I'd expect this to be UB.

Sorry about the space between the # and the define - not sure how that
crept in - its certainly not in the original code.

Have to ask - UB is a new one to me... meaning?

Quote:
>I'd suggest checking the FAQ (just to be sure), and then going straight
>to the Standard if you really need to know.  Or hang around and somebody
>else may even do it for you.

I've already looked in the preprocessor section of the FAQ before
posting here - it was the reason I posted in the first place. I suppose
I ought to hunt down the standard... Something about the language of
standards make me want to ask someone else instead... :-)

Thanks for your reply.

Grant



Mon, 31 Oct 2005 17:28:48 GMT  
 Correct rules for function macro parameter lists
Replying to my own question (always a clever thing to do :-) ):

Looking into this futher, I tracked down at least the one of the
standards. I can't be bothered with reading the boring text (!), but it
at has plenty of examples of the use of macro functions with "missing"
arguments which says what I need. Interestingly none of the examples
(that I've seen thus far) separate the macro name from its parameter
list (i.e. someMacro ( a, b )  - space between 'o' and '(' ). I suppose
if I keep looking I'll find that too! :-)

Grant

Quote:

> Firstly, let me say I'm aware its generally not a good idea to push
> the preprocessor too hard...

> Whilst experimenting with the preprocessor, I found you can get up to
> a little mischief with the parameter list to macro functions, as shown
> in the example I've listed at the end of this message. What'd like to
> know is:

> 1. What are the rules (if any) of supplying "missing" parameters to
> macro functions. (There are quite a few variations to this - I've
> listed some in the code example below.)

> 2. Is it "legal" in the standard to have spaces between the macro
> function and the first left bracket of the parameter list in macro
> invocations? (As in 'exitThis (a)'.) This does parallel the rules for
> parsing "real" functions, so its at least consistent. (I know you can
> have spaces before the left bracket in the macro definition for
> obvious reasons.)

> I've looked in this list's FAQ and in C-ARM (4th Ed. - I'm not up to
> date) but nothing obvious addressing this seems to be present. I have
> a suspicion that the rule is "unexpected behaviour"... but it'd be
> useful to know if there is some set rules in the standard(s) before I
> either exploit this behaviour or try use some other means.

> Only the third and last invocations of someMacro() generate a warning
> in cpp when -Wall is applied: cpp seems to be happy as long as the
> right number of commas are present.

> Grant

> The code:
> -------------------------------------------------------
> #define voidThing
> # define exitThis(x)  return x
> exitThis(a) ;
> exitThis() ;
> exitThis( voidThing ) ;
> exitThis (a) ;

> #define someMacro(x,y) thisis(x) ; thatis(y)
> someMacro(a,b)
> someMacro(a,)
> someMacro(a)
> someMacro(,b)
> someMacro(,)
> someMacro()
> -------------------------------------------------------
> generates:
> -------------------------------------------------------
> return a ;
> return  ;
> return    ;
> return a ;

> thisis(a) ; thatis(b)
> thisis(a) ; thatis()
> thisis(a) ; thatis()
> thisis() ; thatis(b)
> thisis() ; thatis()
> thisis() ; thatis()
> -------------------------------------------------------



Mon, 31 Oct 2005 19:58:02 GMT  
 Correct rules for function macro parameter lists

Quote:
>1. What are the rules (if any) of supplying "missing" parameters to
>macro functions. (There are quite a few variations to this - I've listed
>some in the code example below.)

C89, 3.8.3 Macro replacement

    Constraints
...
    The number of arguments in an invocation of a function-like macro
    shall agree with the number of parameters in the macro definition, and
    there shall exist a ) preprocessing token that terminates the
    invocation.

A constraint violation requires a compiler diagnostic.

Quote:
>2. Is it "legal" in the standard to have spaces between the macro
>function and the first left bracket of the parameter list in macro
>invocations? (As in 'exitThis (a)'.)

Yes, it is legal (no double quotes needed).

    Each subsequent instance of the function-like macro name followed
    by a ( as the next preprocessing token introduces the sequence of
    preprocessing tokens that is replaced by the replacement list in the
    definition (an invocation of the macro).

By default, any amount of white space is allowed between preprocessing
tokens.

The C89 standard also mentions a common extension:

    A.6.5.12 Empty macro arguments

    A macro argument may consist of no preprocessing tokens ($3.8.3).

Quote:
>#define voidThing
># define exitThis(x)  return x
>exitThis(a) ;

Correct.

Quote:
>exitThis() ;

Correct if the implementation supports the extension mentioned above.

Quote:
>exitThis( voidThing ) ;

Correct with the extension.

Quote:
>exitThis (a) ;

Correct.

Quote:
>#define someMacro(x,y) thisis(x) ; thatis(y)
>someMacro(a,b)

Correct.

Quote:
>someMacro(a,)

Correct with the extension.

Quote:
>someMacro(a)

Incorect.  One argument instead of two.

Quote:
>someMacro(,b)

Correct with the extension.

Quote:
>someMacro(,)

Correct with the extension.

Quote:
>someMacro()

Incorrect.  One argument (or even no argument, in the absence of the
extension) instead of two.

Of course, the invocations relying on the extension cannot be used in
portable code.

Dan
--
Dan Pop
DESY Zeuthen, RZ group



Mon, 31 Oct 2005 21:18:08 GMT  
 Correct rules for function macro parameter lists

Quote:



BTW, Dan Pop's answer was (as usual) excellent.

Quote:
> >>#define voidThing
> >># define exitThis(x)  return x
> >>exitThis() ;

> >I'd expect this to be UB.

> Sorry about the space between the # and the define - not sure how that
> crept in - its certainly not in the original code.

Doesn't matter in modern C, as long as there aren't any non-whitespace
characters between '#' and 'define'.

Quote:
> Have to ask - UB is a new one to me... meaning?

Undefined Behavior.  If you hang around here, you'll see this a lot.

-Arthur



Tue, 01 Nov 2005 08:55:01 GMT  
 Correct rules for function macro parameter lists

Quote:


...
> The C89 standard also mentions a common extension:

>     A.6.5.12 Empty macro arguments

>     A macro argument may consist of no preprocessing tokens ($3.8.3).

> >#define voidThing
> ># define exitThis(x)  return x
> >exitThis(a) ;

> Correct.

> >exitThis() ;

> Correct if the implementation supports the extension mentioned above.

> >exitThis( voidThing ) ;

> Correct with the extension.

AFAIK, the last one is correct without the extension too.

--
Peter



Thu, 03 Nov 2005 10:59:37 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. Ensuring correct function parameters

2. Copy Registry Entry Without Deleting Old Entry ~ function call parameters not correct

3. Copy Registry Entry Without Deleting Old Entry ~ function call parameters not correct

4. Calling DLL functions without known function name, parameter-list until run-time

5. correct scope rules and for counters

6. Simulate a variable argument list in a macro function

7. Empty Function parameter lists

8. Function parameter lists

9. dynamic parameter list for external function

10. Preferred empty parameter list function declaration.

11. Custom Build Rule Macros in Makefile

12. Is this swap() macro correct?

 

 
Powered by phpBB® Forum Software