By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,913 Members | 1,263 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,913 IT Pros & Developers. It's quick & easy.

need a macro

P: n/a
consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on

I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
the number of valid strings in A, and it in turns calls X.

So at all the places in the code where X is getting called I would use
Y(n, A) as generic call. What would Y be like?

Please note that I cannot control the way X is written, it is a 3rd
party code.

Dec 21 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Ashwani wrote:
consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on

I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
I assume here that you mean X(A[0], A[1], A[2], A[3]....A[n]) as above
the number of valid strings in A, and it in turns calls X.
This is not possible unless n is a literal integer constant (e.g. 3).
So at all the places in the code where X is getting called I would use
Y(n, A) as generic call. What would Y be like?
Assuming that n is a literal integer constant, a simple solution would be:

#define Y(n,A) \
X(Y_##n(A))

#define Y_0(a) a[0]
#define Y_1(a) Y_0(a),a[1]
#define Y_2(a) Y_1(a),a[2]
#define Y_3(a) Y_2(a),a[3]
#define Y_4(a) Y_3(a),a[4]
....
#define Y_126(a) Y_125(a),a[126]

Otherwise a computed solution would require a 3rd party cpp lib (you
will have less to write, but more macros defined):

#include <fpp.h// my cpp lib, not standard, load about 400-500 macros

#define Y(n,A) \
X FPP_MAP2(FPP_DUP(n,A),FPP_NCAR(FPP_SEQ_N0(),n),Y_)
#define Y_(A,i) \
A[i]

Y(3,a) -X(a[0],a[1],a[2])

(FPP_SEQ_N0() generate a list of integers starting at 0)

hope this help.

a+, ld.
Dec 21 '06 #2

P: n/a
Laurent Deniau wrote:
Ashwani wrote:
>consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on

I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
I assume here that you mean X(A[0], A[1], A[2], A[3]....A[n]) as above
Sorry, if n is the number of valid strings, then it should be:

X(A[0], A[1], A[2], A[3]....A[n-1])
>the number of valid strings in A, and it in turns calls X.

This is not possible unless n is a literal integer constant (e.g. 3).
>So at all the places in the code where X is getting called I would use
Y(n, A) as generic call. What would Y be like?

Assuming that n is a literal integer constant, a simple solution would be:
With the corrected version:
#define Y(n,A) \
X(Y_##n(A))

#define Y_1(a) a[0]
#define Y_2(a) Y_1(a),a[1]
#define Y_3(a) Y_2(a),a[2]
#define Y_4(a) Y_3(a),a[3]
#define Y_5(a) Y_4(a),a[4]
...
#define Y_127(a) Y_126(a),a[126]
Y(3,a) -X(a[0],a[1],a[2])

a+, ld.
Dec 21 '06 #3

P: n/a
"Ashwani" <am****@yahoo.comwrote:
consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on
I presume this is a variadic function?
I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
the number of valid strings in A, and it in turns calls X.

So at all the places in the code where X is getting called I would use
Y(n, A) as generic call. What would Y be like?
In the general case, this is not possible. You can write hacks for
specific cases, but unfortunately there is no ISO C way to construct a
variable argument list at run time.

Richard
Dec 21 '06 #4

P: n/a
Ashwani wrote:
consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on

I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
the number of valid strings in A, and it in turns calls X.

So at all the places in the code where X is getting called I would use
Y(n, A) as generic call. What would Y be like?

Please note that I cannot control the way X is written, it is a 3rd
party code.
Note that if n is not a constant literal, you can still use a wrapper
function like:

void Y(int n, char *A[])
{
switch(n) {
case 0: break;
case 1: X(A[0]); break;
case 2: X(A[0],A[1]); break;
...
case 127: X(A[0], .., A[126]); break;
default: abort();
}
}

If speed matters for small size you can do:

static inline void Y(int n, char *A[])
{
extern void Y_(int,char**);

switch(n) {
case 0: break;
case 1: X(A[0]); break;
case 2: X(A[0],A[1]); break;
case 3: X(A[0],A[1],A[2]); break;
default: Y_(n,A);
}
}

where Y_ is equivalent to the first Y above without the 4 first cases.

After optimisation, Y(2,A) will be equivalent to X(A[0],A[1]) and Y(4,A)
to Y_(4,A) but Y(n,A) will inline the code of Y including the call to
Y_. For n>3 the extra function call is probably negligeable.

a+, ld.
Dec 21 '06 #5

P: n/a
Ashwani wrote:
consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on

I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
the number of valid strings in A, and it in turns calls X.
C99 compilers, and several not-yet-C99 compilers when not invoked for
C90 (or C89) compliance, offer the ability to declare X as
X_return_type X(size_t n, char *array[n]);
If you have such a compiler, you need no such macro.

BTW, your function as you described it cannot work. Functions with a
variable number of arguments need an initial segment specifying a known
argument. That is
X_return_type X( ... );
is not a legal prototype, Since you must have something like
X_return_type X(size_t n, ...);
the C99-style function prototype above looses nothing and avoids the use
of <stdargs.hmacros.
Dec 21 '06 #6

P: n/a
Martin Ambuhl wrote:
Ashwani wrote:
consider A is of type char *A[]
there is this function X which takes variable number of "char * "
arguments, so X can be called like

X (A[0]) or
X(A[0], A[1]) or
X(A[0], A[1], A[3]) and so on

I have to call this function X from different places in the code.

But I want to make the calling of X as generic as possible so I would
like to have a wrapper function or a macro Y such that instead of
calling X( A[1], A[2], A[3]....A[n]) I would call Y(n, A) where n is
the number of valid strings in A, and it in turns calls X.

C99 compilers, and several not-yet-C99 compilers when not invoked for
C90 (or C89) compliance, offer the ability to declare X as
X_return_type X(size_t n, char *array[n]);
If you have such a compiler, you need no such macro.
This is equivalent to

X_return_type X(size_t n, char *array[]);

except for a gratuitous incompatibility with C90.

Dec 21 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.