Вы могли бы сделать следующее:
#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));
}
}
Это выводит:
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
Чтобы определить случай p<1 || p>4
внутри макроса, вы можете изменить одну из тернарных операций, чтобы она выглядела следующим образом (первая в данном случае):
(p) == 1 \
?(v) \
:((p) < 1 || (p) > 4 \
?fflush(stdout), fprintf(stderr, "Invalid: %d", v), exit(EXIT_FAILURE), -1 \
:0), \
Результат тогда выглядел так:
i = 0: Invalid: 0
Обратите внимание, что макрос не может пропустить вызов функции, а только либо вызывает функцию, либо завершает программу, как это делает пример выше.
Чтобы иметь возможность продолжать работу, можно можно изменить макрос, чтобы фактически выполнять вызов функции:
#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");
}
}
}
Это выведет:
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
Эта линия
if (-1 == setACports2(foo, i, vi))
расширится до:
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 ) ))
Поскольку setACports2
дублирует setACports
, это может также выглядеть так:
#define setACports2(f, p, v) ( \
((p) < 1 || (p) > 4) \
? fflush(stdout), errno = ERANGE, perror(#f "()"), -1 \
: ( \
f(setACports(p, v)), 0 \
) \
)
Дальнейшие чтения, связанные с этим ответом:
person
alk
schedule
20.07.2019
p, v
) и использующаяsprintf
для заполнения. В противном случае выделите строку внутри самой функции и верните указатель на нее. Есть ли известное ограничение на то, как долго может бытьv
? - person David C. Rankin   schedule 20.07.2019p
известен и равен1-4
,v
- 8-битное значение,0 - 0xff
- person stdcerr   schedule 20.07.2019