[comp.lang.c] Calling multiple functions in a macro.

daveh@marob.MASA.COM (Dave Hammond) (10/31/88)

In attempting to construct a macro which calls several functions,
but can be used as a single statement (i.e. without braces in an if/else
construct), I can see 2 possible alternatives:

1.
#define FOO()	do { foo1(); foo2(); foo3() foo4(); } while(0)

2.
#define FOO()	foo1(), foo2(), foo3(), foo4()

The first adds quite a bit of code to the program and makes lint
complain about constants in conditional text.

The second compiles, executes and lints correctly (on Xenix), but
is it portable to string function calls in this manner?

Dave Hammond
  UUCP: ...!uunet!masa.com!{marob,dsix2}!daveh
DOMAIN: daveh@marob.masa.com
----------------------------------------------------------------------------

peter@thirdi.UUCP (Peter Rowell) (11/02/88)

In article <353@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes:
>...
>2.
>#define FOO()	foo1(), foo2(), foo3(), foo4()
>...
>The second compiles, executes and lints correctly (on Xenix), but
>is it portable to string function calls in this manner?

What you have is an expression using the comma operator.  Expressions
are one of the basic statement types in C.  If this isn't portable
using a given C compiler, then it isn't a C compiler.

See K&R, pg 192, Appendix A, 7.15 "Comma operator"

One suggestion: wrap the whole thing in parens to prevent any possible
nasty side effects.

#define FOO()	(foo1(), foo2(), foo3(), foo4())

"... Comma comma comma come on, yeah yeah yeah..."
		    James Taylor
----------------------------------------------------------------------
Peter Rowell
Third Eye Software, Inc.		(415) 321-0967
Menlo Park, CA  94025			...!pyramid!thirdi!peter

knudsen@ihlpl.ATT.COM (Knudsen) (11/02/88)

In article <353@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:


> #define FOO()	do { foo1(); foo2(); foo3() foo4(); } while(0)

Why use the do and while?  C has blocks, you can say just plain
	{foo1(); ... foo4();}
Of course all you're really doing is supplying the braces so the
macro can be used "without braces" in the source.
I dimly recall defining macros wrapped in {}; they worked fine.


> #define FOO()	foo1(), foo2(), foo3(), foo4()
               (                              )
This should work as-is, and also yield the value of foo4().
I'd wrap the definition in parentheses, though, as shown.

I'd say that in the first example, {} are the sequential
equivalent to () in the second, in the sense of keeping you
out of trouble in any context.
-- 
Mike Knudsen  Bell Labs(AT&T)   att!ihlpl!knudsen
"Lawyers are like nuclear bombs and PClones.  Nobody likes them,
but the other guy's got one, so I better get one too."

pmech@oucsace.cs.OHIOU.EDU (Paul J. Mech) (11/02/88)

In article <353@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
+ In attempting to construct a macro which calls several functions,
+ but can be used as a single statement (i.e. without braces in an if/else
+ construct), I can see 2 possible alternatives:
+ 
+ 1.
+ #define FOO()	do { foo1(); foo2(); foo3() foo4(); } while(0)
+ 
+ 2.
+ #define FOO()	foo1(), foo2(), foo3(), foo4()
+ 
how about

#define FOO() { foo1(); foo2(); foo3(); foo4(); }

bill@twwells.uucp (T. William Wells) (11/02/88)

In article <353@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes:
: In attempting to construct a macro which calls several functions,
: but can be used as a single statement (i.e. without braces in an if/else
: construct), I can see 2 possible alternatives:
:
: 1.
: #define FOO() do { foo1(); foo2(); foo3() foo4(); } while(0)
:
: 2.
: #define FOO() foo1(), foo2(), foo3(), foo4()
:
: The first adds quite a bit of code to the program and makes lint
: complain about constants in conditional text.

The first is unlikely to add that much to the code. Go look at the
assembly output.

: The second compiles, executes and lints correctly (on Xenix), but
: is it portable to string function calls in this manner?

Yes it is portable. But save yourself some headaches and write it:

#define FOO() (foo1(), foo2(), foo3(), foo4())

The extra parentheses can prevent problems with, e.g.:

	a + FOO()

which would otherwise add a to the result of foo1 and toss the
result, when what you want it to do is add it to foo4 and return the
result.

---
Bill
{uunet|novavax}!proxftl!twwells!bill

ok@quintus.uucp (Richard A. O'Keefe) (11/02/88)

In article <7462@ihlpl.ATT.COM> knudsen@ihlpl.ATT.COM (Knudsen) writes:
>In article <353@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
>> #define FOO()	do { foo1(); foo2(); foo3() foo4(); } while(0)
>Why use the do and while?  C has [compound statements], you can say just plain
>	{foo1(); ... foo4();}

Answer: so you can write if (test) foo(); else baz();
With Hammond's definition, the expansion is
	if (test) do { ... } while (0); else baz();
which is valid.  With Knudsen's definition, the expansion is	
	if (test) { ... } ; else baz();
which is **not** syntactically valid.  

If you want a macro to be usable as an expression, use (...)
If you want a macro to be usable as a statement, use do { ... } while (0)

If C had remained syntactically closer to BCPL and copied less of PL/I's
syntactic arsenic, we'd have been spared a fair bit of irritation.

daveh@marob.MASA.COM (Dave Hammond) (11/03/88)

In article <7462@ihlpl.ATT.COM> knudsen@ihlpl.ATT.COM (Knudsen) writes:
>In article <353@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
>> #define FOO()	do { foo1(); foo2(); foo3() foo4(); } while(0)
>Why use the do and while?  C has blocks, you can say just plain
>	{foo1(); ... foo4();}
>Of course all you're really doing is supplying the braces so the
>macro can be used "without braces" in the source.
>I dimly recall defining macros wrapped in {}; they worked fine.

Except that invoking FOO(); (note the semicolon) introduces a null
statement which could easily throw off the flow (or fail to compile)
if used within a conditional expression.  You would have to to invoke
FOO() without a terminating semicolon which, to me, is unnatural.

Dave Hammond
  UUCP: ...!uunet!masa.com!{marob,dsix2}!daveh
DOMAIN: daveh@marob.masa.com
----------------------------------------------------------------------------