警告,前方有黑魔法。
确实可以使用宏,尽管有预设数量的参数。这个数字可以是任意的,但每个数字都必须手写:
#include <stdio.h>
#include <stdlib.h>
#define MERGE_EXPAND( a , b ) a##b
#define MERGE( a , b ) MERGE_EXPAND( a , b )
#define COUNT_PICK( a , b , c , pick , ... ) pick
#define COUNT( ... ) COUNT_PICK( __VA_ARGS__ , 3 , 2 , 1 , 0 )
#define JOIN_1( a ) a
#define JOIN_2( a , b ) a##b
#define JOIN_3( a , b , c ) a##b##c
#define JOIN( ... ) MERGE( JOIN_ , COUNT( __VA_ARGS__ ) )( __VA_ARGS__ )
int main( void )
{
printf( "%d\n" , JOIN( 12345 ) ) ;
printf( "%d\n" , JOIN( 100,44 ) ) ;
printf( "%d\n" , JOIN( -10,44,9999 ) ) ;
return EXIT_SUCCESS ;
}
宏 COUNT 计算传递给它的参数数量。这是通过将参数传递给辅助宏 COUNT_PICK 并添加附加参数(按相反顺序的连续数字)来完成的。然后,传递给 COUNT 的原始参数数量会操纵 COUNT_PICK 的参数,以便选择其中一个数字。
然后将该选定的数字与 JOIN 合并,产生 JOIN_1、JOIN_2 或 JOIN_3。然后,所选宏与原始参数一起使用,并将它们简单地合并为单个整数文字。
可以通过手动定义更多 JOIN_X 宏来扩展此示例,其中 X 是连续数字。同时宏 COUNT 和 COUNT_PICK 也必须更改。
作为额外的好处,传递无效参数,例如:
JOIN( 10,+44 );
JOIN( 10,-44 );
JOIN( 10,*44 );
JOIN( 10,/44 );
JOIN( /10,44 );
//etc...
将产生编译时警告,但仍然允许使用会产生有效整数常量的参数。
要与 Microsoft 编译器一起使用,并使用 SVC14(Microsoft Visual Studio 2015 Update 3)进行测试,必须修改代码。宏 COUNT_PICK 和 MERGE 必须用附加的扩展宏包装:
#define EXPAND(...) __VA_ARGS__