带有三元运算符的宏 - 我可以在运行时通过变量漏斗吗?
macro with ternary operator - can I funnel through variable at runtime?
我想知道是否可以通过预处理器宏汇集非静态变量。
想象一下,我必须调用一个带有 4 个参数的函数,例如 foo(A,B,C,D);
我的输入是 bar
,它是一个介于 1 和 4 之间的整数值,而 baz
可以是运行时的任何整数值,如果 'bar' == 1,则进入 A,如果是,则进入 B' == 2 ... D 如果它是 == 4。
我想出了一个看起来像这样的宏:
#define setACports(p,v) ((p) == 4 ? ", , ,(v)," : \
((p) == 3 ? ", ,(v), ," : \
((p) == 2 ? ",(v), , ," : \
(((p) == 1 ? "(v), , , ," : "invalid")))))
/*example application */
void foo(int var1,int var2,int var3, int var4);
int main (void) {
int i = 0;
for (i=0;i<5;i++)
foo(setACports(i,i));
}
现在,虽然参数 "positioning" 工作正常,但值显然不能正常工作,因为 (v)
在预处理器时不可用。我将如何最好地实施这样的事情?我很困惑什么可能是最好的解决方案,任何建议或提示都会很棒!
对于这个特定示例,由于您正在打印,因此可以将 v
替换为 %d
并将参数附加到末尾。
#define setACports(p,v) ((p) == 4 ? ", , ,(%d)," : \
((p) == 3 ? ", ,(%d), ," : \
((p) == 2 ? ",(%d), , ," : \
(((p) == 1 ? "(%d), , , ," : "invalid"))))), (v)
输出:
invalid(1), , , ,,(2), , ,, ,(3), ,, , ,(4),
你可以做:
#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
的情况,您 可以 修改其中一个 ternary-operations 看起来像这样(在这种情况下是第一个):
(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 \
) \
)
与此答案相关的进一步阅读:
- Seeing expanded C macros
- What does the comma operator , do?
- stderr and stdout - buffered vs. not buffered?
- How to know what the 'errno' means?
我想知道是否可以通过预处理器宏汇集非静态变量。
想象一下,我必须调用一个带有 4 个参数的函数,例如 foo(A,B,C,D);
我的输入是 bar
,它是一个介于 1 和 4 之间的整数值,而 baz
可以是运行时的任何整数值,如果 'bar' == 1,则进入 A,如果是,则进入 B' == 2 ... D 如果它是 == 4。
我想出了一个看起来像这样的宏:
#define setACports(p,v) ((p) == 4 ? ", , ,(v)," : \
((p) == 3 ? ", ,(v), ," : \
((p) == 2 ? ",(v), , ," : \
(((p) == 1 ? "(v), , , ," : "invalid")))))
/*example application */
void foo(int var1,int var2,int var3, int var4);
int main (void) {
int i = 0;
for (i=0;i<5;i++)
foo(setACports(i,i));
}
现在,虽然参数 "positioning" 工作正常,但值显然不能正常工作,因为 (v)
在预处理器时不可用。我将如何最好地实施这样的事情?我很困惑什么可能是最好的解决方案,任何建议或提示都会很棒!
对于这个特定示例,由于您正在打印,因此可以将 v
替换为 %d
并将参数附加到末尾。
#define setACports(p,v) ((p) == 4 ? ", , ,(%d)," : \
((p) == 3 ? ", ,(%d), ," : \
((p) == 2 ? ",(%d), , ," : \
(((p) == 1 ? "(%d), , , ," : "invalid"))))), (v)
输出:
invalid(1), , , ,,(2), , ,, ,(3), ,, , ,(4),
你可以做:
#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
的情况,您 可以 修改其中一个 ternary-operations 看起来像这样(在这种情况下是第一个):
(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 \
) \
)
与此答案相关的进一步阅读:
- Seeing expanded C macros
- What does the comma operator , do?
- stderr and stdout - buffered vs. not buffered?
- How to know what the 'errno' means?