You could do:
#include <stdio.h>
#define setACports(p, v) \
(p) == 1 ?(v) :0, \
(p) == 2 ?(v) :0, \
(p) == 3 ?(v) :0, \
(p) == 4 ?(v) :0
void foo(int var1, int var2, int var3, int var4)
{
printf("var1 = %d, var2 = %d, var3 = %d, var4 = %d\n",
var1, var2, var3, var4);
}
int main(void)
{
for (int i = 0; i < 5; ++i)
{
printf("i = %d: ", i);
foo(setACports(i, i));
}
}
This outputs:
i = 0: var1 = 0, var2 = 0, var3 = 0, var4 = 0
i = 1: var1 = 1, var2 = 0, var3 = 0, var4 = 0
i = 2: var1 = 0, var2 = 2, var3 = 0, var4 = 0
i = 3: var1 = 0, var2 = 0, var3 = 3, var4 = 0
i = 4: var1 = 0, var2 = 0, var3 = 0, var4 = 4
To detect the case of p<1 || p>4
inside the macro you could modify one of the ternary-operations to look like this (the 1st one in this case):
(p) == 1 \
?(v) \
:((p) < 1 || (p) > 4 \
?fflush(stdout), fprintf(stderr, "Invalid: %d", v), exit(EXIT_FAILURE), -1 \
:0), \
The output then looked like this:
i = 0: Invalid: 0
Please note that the macro cannot skip the function call, but only either call the function or end the program, as the example above does.
To be able to continue running one could modify the macro to actually do the function call:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define setACports2(f, p, v) ( \
((p) < 1 || (p) > 4) \
? fflush(stdout), errno = ERANGE, perror(#f "()"), -1 \
: ( \
f( \
(p) == 1 ?(v) :0, \
(p) == 2 ?(v) :0, \
(p) == 3 ?(v) :0, \
(p) == 4 ?(v) :0 \
), 0 \
) \
)
void foo(int var1, int var2, int var3, int var4)
{
printf("var1 = %d, var2 = %d, var3 = %d, var4 = %d\n",
var1, var2, var3, var4);
}
int main(void)
{
for (int i = 0; i < 5; ++i)
{
int vi = i;
printf("i = %d: ", i);
if (-1 == setACports2(foo, i, vi))
{
fprintf(stderr, "setACports() failed\n");
}
}
}
This would output:
i = 0: foo(): Numerical result out of range
setACports() failed
i = 1: var1 = 1, var2 = 0, var3 = 0, var4 = 0
i = 2: var1 = 0, var2 = 2, var3 = 0, var4 = 0
i = 3: var1 = 0, var2 = 0, var3 = 3, var4 = 0
i = 4: var1 = 0, var2 = 0, var3 = 0, var4 = 4
This line
if (-1 == setACports2(foo, i, vi))
would expand to:
if (-1 == ( ((i) < 1 || (i) > 4) ? fflush(stdout), errno = ERANGE, perror("foo" "()"), -1 : ( foo((i) == 1 ?(vi) :0, (i) == 2 ?(vi) :0, (i) == 3 ?(vi) :0, (i) == 4 ?(vi) :0), 0 ) ))
As setACports2
duplicates setACports
it could also look like this:
#define setACports2(f, p, v) ( \
((p) < 1 || (p) > 4) \
? fflush(stdout), errno = ERANGE, perror(#f "()"), -1 \
: ( \
f(setACports(p, v)), 0 \
) \
)
Further readings related to this answer: