زبان C با پارامترهای متغیر ماکرو می شود و پارامتر 0 به طور نادرست 1 را برنمی گرداند. هر دو GCC و MSVC عبور می کنند

مرجع: https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments
من ابتدا از آن استفاده کردم:
#define _expand(x) x
#define _numargs(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, N, ...) N
#define numargs(...) _expand(_numargs(_, ##__VA_ARGS__, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
MSVC باید استفاده شود_expand
گفته می شود که دلیل آن زمان گسترش پارامتر است ، اما پارامتر صفر نتیجه خطا را به دست می آورد. 1 مشکل دیگر با GCC وجود دارد ، این است که به عنوان مثال نمی توان از آن استفاده کرد.-std=c99
-std=c23
، در غیر این صورت پارامتر صفر نیز 1 است ، زیرا##
این یک پسوند GCC است ، به https://gcc.gnu.org/onlinedocs/cpp/variadic-macros.html مراجعه کنید ، و استاندارد C تا C23 اضافه نمی شود.__VA_OPT__
، جالب اینجاست که MSVC نیز از آن پشتیبانی می کند##
。
مثل این(sizeof((int[]){__VA_ARGS__})/sizeof(int))
اول از همه ، MSVC باید نسخه بالاتری باشد و یک هشدار عدم تطابق از نوع C4047 را گزارش می کند ، در حالی که GCC یک خطا است و نمی تواند گردآوری شود.
فقط 6 پاسخ زیر مناسب است ، من آن را کمی تنظیم کردم تا متناسب با سبک شخصی خود باشد:
#define _numargs_call(__arg_0, __arg_1) __arg_0 __arg_1
#define _numargs_select(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, __arg_0, ...) __arg_0
#define numargs(...) _numargs_call(_numargs_select, (_, ##__VA_ARGS__, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
اکنون MSVC استفاده شده است_numargs_call
اگر می خواهید آن را تنظیم کنید ، با پارامترهای صفر مشکلی وجود نخواهد داشت و حتی VS2007/WDK7.1 باستانی طبیعی است.
کد آزمون:
int main() {
printf("numargs = %d\n", numargs());
printf("numargs = %d\n", numargs(1));
printf("numargs = %d\n", numargs(1, 3.14));
printf("numargs = %d\n", numargs(1, 3.14, "hello"));
return EXIT_SUCCESS;
}
اجراcl test.c && test.exe
یاgcc -o test.exe test
، نتایج عبارتند از:
.c && ./test.exe
numargs = 0
numargs = 1
numargs = 2
numargs = 3