读 glibc 中 关于 socket 系统调用实现的部分,然后看到了这里,写在这里做份一份笔记。
#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n #define __SYSCALL_NARGS(...) \ __SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,) #define __SYSCALL_CONCAT_X(a,b) a##b #define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b) #define __SYSCALL_DISP(b,...) \ __SYSCALL_CONCAT (b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
__VA_ARGS__ 代表首层的所有的宏参数,在 __SYSCALL_NARGS_X 中做参数替换,而 __SYSCALL_NARGS_X 通过额外增加参数(7,6,5,4,3,2,2,0,)来确定
__VA_ARGS__ 中究竟传进来多少个参数,从而拼接出究竟要调用哪一个类型的函数
测试代码如下
#include <stdio.h> #define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n #define __SYSCALL_NARGS(...) \ __SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
int main(int argc,char* argv[]) { int paramCnt1 = __SYSCALL_NARGS(1); int paramCnt2 = __SYSCALL_NARGS(1,2); int paramCnt3 = __SYSCALL_NARGS(1,2,3); int paramCnt4 = __SYSCALL_NARGS(1,2,3,4);
printf("param cnt1:%d\n", paramCnt1); printf("param cnt2:%d\n", paramCnt2); printf("param cnt3:%d\n", paramCnt3); printf("param cnt4:%d\n", paramCnt4); return 0; }
测试代码结果如下: