提问人:swineone 提问时间:10/6/2023 更新时间:10/7/2023 访问量:145
C 宏到按位 OR,将可变数量的参数放在一起(不带 P99 的轻量级解决方案)
C macro to bitwise-OR together a variable number of arguments (lightweight solution without P99)
问:
我需要一个按位 ORs 将其(可变数量的)参数组合在一起的宏:
int main() {
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4));
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4, 8, 16));
}
这应该打印:
7
31
我有一个使用 P99 的解决方案:
#include "p99/p99_for.h"
#define P00_IDT(NAME, X, I) X
#define BITWISE_OR_MULTIPLE_ARGS(...) P99_FOR(A, P99_NARG(__VA_ARGS__), P00_BOR, P00_IDT, __VA_ARGS__)
但是,这是我的代码库中 P99 的唯一用途,我发现导入所有 P99 有点重量级。如何使用一组独立的宏来实现这一点?
答:
1赞
nielsen
10/6/2023
#1
您可以使用此答案中的方法。
例如,最多有 5 个参数:
#include <stdio.h>
#define BOR2(a,b) ((a) | (b))
#define BOR3(a,b,c) (BOR2(a,b) | (c))
#define BOR4(a,b,c,d) (BOR3(a,b,c) | (d))
#define BOR5(a,b,c,d,e) (BOR4(a,b,c,d) | (e))
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
#define BITWISE_OR_MULTIPLE_ARGS(...) GET_MACRO(__VA_ARGS__, BOR5, BOR4, BOR3, BOR2)(__VA_ARGS__)
int main()
{
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4));
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4, 8, 16));
return 0;
}
评论
0赞
swineone
10/6/2023
这是一个很好的开始。但是,我正在使用大型位域(带有 64 位变量),因此我可能需要多达 64 个参数——我不太可能使用所有这些参数,但肯定超过 5 个。我想我在某处看到了一个技巧,所以你可以只构建对数数量的宏,等?BOR2
BOR3
3赞
Michael Walsh Pedersen
10/6/2023
#2
您可以使用 2 个宏来完成:
#define A(a0,a1,a2,a3,a4,a5,a6,a7,b0,b1,b2,b3,b4,b5,b6,b7,\
c0,c1,c2,c3,c4,c5,c6,c7,d0,d1,d2,d3,d4,d5,d6,d7,e0,e1,e2,e3,e4,e5,e6,e7,\
f0,f1,f2,f3,f4,f5,f6,f7,g0,g1,g2,g3,g4,g5,g6,g7,h0,h1,h2,h3,h4,h5,h6,h7,...)\
a0|a1|a2|a3|a4|a5|a6|a7|b0|b1|b2|b3|b4|b5|b6|b7|c0|c1|c2|c3|c4|c5|c6|c7|\
d0|d1|d2|d3|d4|d5|d6|d7|e0|e1|e2|e3|e4|e5|e6|e7|f0|f1|f2|f3|f4|f5|f6|f7|\
g0|g1|g2|g3|g4|g5|g6|g7|h0|h1|h2|h3|h4|h5|h6|h7
#define B(...) A(__VA_ARGS__,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
#include <stdio.h>
int main()
{
printf("%d\n",B(1,2,4,8));
printf("%d\n",B(1,2,4,8,16));
}
1赞
David Ranieri
10/7/2023
#3
使用复合文字的另一种方法:
#include <stdio.h>
#define BITWISE_OR_MULTIPLE_ARGS(...) \
bitwise_or_multiple_args( \
(int []){__VA_ARGS__}, \
sizeof((int []){__VA_ARGS__}) / sizeof(int) \
)
static int bitwise_or_multiple_args(int *arr, size_t n)
{
int rc = 0;
for (size_t i = 0; i < n; i++)
{
rc |= arr[i];
}
return rc;
}
int main(void)
{
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4));
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4, 8, 16));
return 0;
}
或与可变参数函数结合使用:
#include <stdio.h>
#include <stdarg.h>
#define BITWISE_OR_MULTIPLE_ARGS(...) \
bitwise_or_multiple_args( \
sizeof((int []){__VA_ARGS__}) / sizeof(int), \
__VA_ARGS__ \
)
static int bitwise_or_multiple_args(size_t n, ...)
{
int rc = 0;
va_list args;
va_start(args, n);
for (size_t i = 0; i < n; i++)
{
rc |= va_arg(args, int);
}
va_end(args);
return rc;
}
int main(void)
{
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4));
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4, 8, 16));
return 0;
}
在 gcc/clang 下,您可以使用语句表达式来避免辅助函数:
#include <stdio.h>
#define BITWISE_OR_MULTIPLE_ARGS(...) __extension__ \
({ \
int arr[] = {__VA_ARGS__}; \
size_t n = sizeof arr / sizeof(arr[0]); \
int rc = 0; \
\
for (size_t i = 0; i < n; i++) \
{ \
rc |= arr[i]; \
} \
rc; \
})
int main(void)
{
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4));
printf("%d\n", BITWISE_OR_MULTIPLE_ARGS(1, 2, 4, 8, 16));
return 0;
}
评论
P99_BORS(...)