/Слага шапка на Индиана Джоунс/
Може да съм малко закъснял, но съм тук, за да кажа, че този проблем има подходящо (не) решение.
Първо, някои предпоставки дефинират (обяснение тук ):
#define L(c, ...) \
L4(c,1,0,,,,,,,,,,,,,##__VA_ARGS__) L4(c,0,1,,,,,,,,,##__VA_ARGS__) \
L4(c,0,2,,,,, ##__VA_ARGS__) L4(c,0,3, ##__VA_ARGS__)
#define L4(c, f, n, ...) \
L3(c,f,n##0,,,,__VA_ARGS__) L3(c,0,n##1,,,__VA_ARGS__) \
L3(c,0,n##2,, __VA_ARGS__) L3(c,0,n##3, __VA_ARGS__)
#define L3(...) L2(__VA_ARGS__, \
1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, )
#define L2(c, f, \
n00,n01,n02,n03, n04,n05,n06,n07, n08,n09,n0A,n0B, n0C,n0D,n0E,n0F, \
a00,a01,a02,a03, a04,a05,a06,a07, a08,a09,a0A,a0B, a0C,a0D,a0E,a0F, \
s, ...) L##s(c, f, n00, a00)
#define L1(c, f, n, a) c##f(n, a)
#define L0(c, f, n, a)
След това кодът, който всъщност е разширение на отговора на @alk:
#include <stdio.h>
#define STRING1(n, a) #a, (a)
#define STRING0(n, a) , STRING1(n, a)
#define PRINTF(fmt, ...) printf(fmt, L(STRING, __VA_ARGS__))
int main(int argc, char *argv[]) {
int i = 42;
char ch = 'a';
char str[4] = "alk";
/** every var must be preceded with '%s' for its name to be shown **/
PRINTF("%s=%s, %s=%c, %s=%d\n", str, ch, i);
return 0;
}
Тази версия е подходяща само за [0..16] аргументи, но може лесно да се разшири до произволен брой аргументи, особено до степени на 2. Въпреки това, колкото повече аргументи поддържа, толкова по-малко елегантно изглежда.
P.S.: @BasileStarynkevitch вече предостави всички правилни връзки, за да изясни как работи това.
person
hidefromkgb
schedule
18.10.2016
"%d %f %c %s"
не може да бъде разделен, разширен по средата или модифициран от C препроцесора. Може да работи само за единични параметри, тъй като конкатенацията на низ позволява добавяне на друг низ към литерал на низ. - person Jens   schedule 07.01.2014