C function macro question

A

Ann O'Nymous

I have a C function macro defined something like this:

void f1(int *, int);
void f2(int *, int);
....
#define FOO(i,j)\
{ int k[10];\
f1(k,i);\
f2(k,j);\
}
....

and calls like FOO(123,456); work fine.

Now I want to change f2 to return an int, and change FOO to return that int.

int xyz;
....
xyz = FOO(123,456);

The preprocessor would expand that as follows:

xyz = { int k[10];
f1(k,123);
f2(k,456);
}

Is it possible to rework FOO so it does the equivalent of this:

{ int k[10];
f1(k,123);
xyz = f2(k,456);
}

I can do it with a hidden variable in FOO:

....
l = f2(k,j);

and calling it like this:

FOO(123,456);
xyz = l;

which is poor style, someday some poor sap will wonder where "l" came from.

I could also add a third parameter for the output value.
#define FOO(i,j,l)\
....
l = f2(k,j);

and the call would be:

FOO(123,456,xyz);

Is there a better way? I want to use the xyz=FOO(123,456) form.
 
B

Ben Pfaff

Ann O'Nymous said:
I have a C function macro defined something like this:

void f1(int *, int);
void f2(int *, int);
...
#define FOO(i,j)\
{ int k[10];\
f1(k,i);\
f2(k,j);\
}
...

and calls like FOO(123,456); work fine.

Now I want to change f2 to return an int, and change FOO to return that int.

int xyz;
...
xyz = FOO(123,456);

You are probably best off using an inline function:

static inline int foo(int *i, int j)
{
int k[10];
f1(k, i);
return f2(k, j);
}
 
T

Tom St Denis

I have a C function macro defined something like this:

void f1(int *, int);
void f2(int *, int);
...
#define FOO(i,j)\
   { int k[10];\
     f1(k,i);\
     f2(k,j);\
   }
...

and calls like FOO(123,456); work fine.

Now I want to change f2 to return an int, and change FOO to return that int.

int xyz;
...
xyz = FOO(123,456);

The preprocessor would expand that as follows:

xyz = { int k[10];
         f1(k,123);
         f2(k,456);
       }

Is it possible to rework FOO so it does the equivalent of this:

  { int k[10];
    f1(k,123);
    xyz = f2(k,456);
  }

I can do it with a hidden variable in FOO:

...
   l = f2(k,j);

and calling it like this:

FOO(123,456);
xyz = l;

which is poor style, someday some poor sap will wonder where "l" came from.

I could also add a third parameter for the output value.
#define FOO(i,j,l)\
...
l = f2(k,j);

and the call would be:

FOO(123,456,xyz);

Is there a better way?  I want to use the xyz=FOO(123,456) form.

There is a trick that works with GCC at least


tom-st-deniss-MacBook:~ tomstdenis$ cat test.c
#include <stdio.h>

#define func() ({\
int x, y; for (y = x = 0; x < 100; x++) y += x; y; })

int main(void)
{
printf("func == %d\n", func());
return 0;
}

Basically you turn a compound statement into an expression. As far as
I can tell the value of the last statement is what is returned.

I don't think it's portable C but if you're just in GCC it should
work.

Tom
 
A

Ann O'Nymous

You are probably best off using an inline function:

I would be, except I simplified the problem too much. I am actually
using the variadic functions, which is why I am using the macro function
definition, and the call to f1 is really like:

#include <stdarg.h>

#define FOO(i,...)\
{ int k[10];\
f1(k,__VA_ARGS__);\
f2(k,i);\
}

I suppose I could use the run-time form (va_list, va_start, va_arg etc.)
 
E

Eric Sosman

You are probably best off using an inline function:

I would be, except I simplified the problem too much. I am actually
using the variadic functions, which is why I am using the macro function
definition, and the call to f1 is really like:

#include <stdarg.h>

#define FOO(i,...)\
{ int k[10];\
f1(k,__VA_ARGS__);\
f2(k,i);\
}

I suppose I could use the run-time form (va_list, va_start, va_arg etc.)

Yes, assuming you can rewrite f1(). That's often a good idea
with variadic functions anyhow: Write one function that takes a
va_list and does the real work, and make the variadic function be
just a wrapper for it:

void f1_guts(int *k, va_list ap) {
/* the real work happens here */
}

void f1(int *k, ...) {
va_list ap;
va_start(ap, k);
f1_guts(k, ap);
va_end(ap);
}

Now you can use an inline function that calls f1_guts() instead of
a macro that tries to cobble up a call to f1():

inline int FOO(int i, ...) {
int k[10];
va_list ap;
va_start(ap, i);
f1_guts(k, ap);
va_end(ap);
return f2(k, i);
}

Having both f1() and f1_guts() may turn out to be handy for other
reasons, too -- ponder the fprintf() and vfprintf() pair, for example.
 
N

Nick

Eric Sosman said:
You are probably best off using an inline function:

I would be, except I simplified the problem too much. I am actually
using the variadic functions, which is why I am using the macro function
definition, and the call to f1 is really like:

#include <stdarg.h>

#define FOO(i,...)\
{ int k[10];\
f1(k,__VA_ARGS__);\
f2(k,i);\
}

I suppose I could use the run-time form (va_list, va_start, va_arg etc.)

Yes, assuming you can rewrite f1(). That's often a good idea
with variadic functions anyhow: Write one function that takes a
va_list and does the real work, and make the variadic function be
just a wrapper for it:

void f1_guts(int *k, va_list ap) {
/* the real work happens here */
}

void f1(int *k, ...) {
va_list ap;
va_start(ap, k);
f1_guts(k, ap);
va_end(ap);
}

Now you can use an inline function that calls f1_guts() instead of
a macro that tries to cobble up a call to f1():

inline int FOO(int i, ...) {
int k[10];
va_list ap;
va_start(ap, i);
f1_guts(k, ap);
va_end(ap);
return f2(k, i);
}

Having both f1() and f1_guts() may turn out to be handy for other
reasons, too -- ponder the fprintf() and vfprintf() pair, for example.

This is excellent advice. The odd time I've not written the
va_list-taking function I've ended up adding it later. And clearly the
standardisation people felt similar. Always do this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top