似乎不同的编译器处理带有可变参数的宏略有不同。
对于 C99 兼容的编译器,一个特殊的标识符 __VA_ARGS__
用于表示可变参数列表:
#define MACRO_1(param1, ...) func(param1, __VA_ARGS__)
对于 GNU C 编译器,可以给可变参数列表一个名称:
#define MACRO_2(param1, args...) func(param1, args) // "args..." is the name
但我在 ACPICA 代码中看到以下定义:
#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__)
调用这样的宏是这样的:
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL);
这似乎是 C99 的方法,但是 va_num
似乎没有用。为什么定义?
ADD 1 - 宏的完整定义
#ifdef USE_EFI_FUNCTION_WRAPPER
#define __VA_NARG__(...) \
__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N())
#define __VA_NARG_(...) \
__VA_ARG_N(__VA_ARGS__)
#define __VA_ARG_N( \
_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
#define __RSEQ_N() \
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define __VA_ARG_NSUFFIX__(prefix,...) \
__VA_ARG_NSUFFIX_N(prefix, __VA_NARG__(__VA_ARGS__))
#define __VA_ARG_NSUFFIX_N(prefix,nargs) \
__VA_ARG_NSUFFIX_N_(prefix, nargs)
#define __VA_ARG_NSUFFIX_N_(prefix,nargs) \
prefix ## nargs
/* Prototypes of EFI cdecl -> stdcall trampolines */
UINT64 efi_call0(void *func);
UINT64 efi_call1(void *func, UINT64 arg1);
UINT64 efi_call2(void *func, UINT64 arg1, UINT64 arg2);
UINT64 efi_call3(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3);
UINT64 efi_call4(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4);
UINT64 efi_call5(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4, UINT64 arg5);
UINT64 efi_call6(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4, UINT64 arg5, UINT64 arg6);
UINT64 efi_call7(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7);
UINT64 efi_call8(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7,
UINT64 arg8);
UINT64 efi_call9(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7,
UINT64 arg8, UINT64 arg9);
UINT64 efi_call10(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3,
UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7,
UINT64 arg8, UINT64 arg9, UINT64 arg10);
/* Front-ends to efi_callX to avoid compiler warnings */
#define _cast64_efi_call0(f) \
efi_call0(f)
#define _cast64_efi_call1(f,a1) \
efi_call1(f, (UINT64)(a1))
#define _cast64_efi_call2(f,a1,a2) \
efi_call2(f, (UINT64)(a1), (UINT64)(a2))
#define _cast64_efi_call3(f,a1,a2,a3) \
efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3))
#define _cast64_efi_call4(f,a1,a2,a3,a4) \
efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4))
#define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \
efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
(UINT64)(a5))
#define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \
efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
(UINT64)(a5), (UINT64)(a6))
#define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \
efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7))
#define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \
efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8))
#define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \
efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \
(UINT64)(a9))
#define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \
efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \
(UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \
(UINT64)(a9), (UINT64)(a10))
/* main wrapper (va_num ignored) */
#define uefi_call_wrapper(func,va_num,...) \
__VA_ARG_NSUFFIX__(_cast64_efi_call, __VA_ARGS__) (func , ##__VA_ARGS__)
#else
#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__)
#endif
最佳答案
va_num
只是传递给函数的普通参数,宏会忽略它。
用法一:
当跨不同的编译器设置使用宏时,这种用法很常见,以便在所有这些设置中调用相同的函数,但映射到不同的 func
,这可能(或可能不) 支持 va_num
参数。在这种特殊情况下,func
可能不支持 va_num
参数,因此宏会忽略它。
用法 2:
也可用于处理旧代码,使其易于移植到新版本的宏。
回答您的问题,va_num
参数不是特殊参数。它与任何其他参数一样使用,与 __VA_ARGS__
或类似参数无关。宏的编写者决定给那个参数起那个名字,只是为了说明它应该包含传递的参数的数量,但没有什么更花哨的,也没有编译器注意到。
关于c - `va_num` 在这个可变参数宏中意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44754209/