2014-01-07 7 views
4

Я хочу написать переменный макрос, который каким-то образом знает имена переданных аргументов. Например:Написание вариационного макроса, который использует имена переданных аргументов

Код:

int x = 2; 
float f = 4.6; 
char c = 'A'; 
char* str = "Bla bla"; 
PRINT("%d %f %c %s", x, f, c, str);  // calling the macro 

должны производить вывод

x=2 f=4.6 c=A str=Bla bla. 

Надежда кто-то знает ответ на этот вопрос.

+0

для char print are% c и не% s Я обновил вопрос с этим – MOHAMED

+1

Я уверен, что это невозможно. – JeremyP

+0

К OP: вы уверены, что хотите * точно * что? Это нелегко сделать! (Но если вы проводите несколько дней или недель работы, вы можете получить что-то близкое). –

ответ

1

Прочитано тщательно документация cpp. В частности, около macro arguments, stringification, concatenation и variadic macros. Это хорошо объяснено.

Возможно, вы, возможно, не сможете достичь именно того, что хотите, потому что вам нужно разбить строку формата.

Возможно снизить ваши цели (например, принимать только один аргумента для PRINT см this или that ответов) или рассмотреть возможность использования более мощный препроцессора как GPP.

Возможно, вы также можете настроить GCC (добавив свои встроенные функции), например. MELT, но это, вероятно, не стоит недель усилий (для новичков), необходимых для этого.

-1

Следующие работы для меня в GCC 4.7:

#include <stdio.h> 
#define PRINT(...) fprintf (stderr, __VA_ARGS__) 

int main() 
{ 
int x = 2; 
float f = 4.6; 
char c = 'A'; 
char* str = "Bla bla"; 
PRINT("%d %f %c %s", x, f, c, str); // calling the macro 
} 

(обратите внимание, что я редактировал вызов макроса изменяющих% s на% с)

С уважением

+1

. Оно также не отображает * имя * 'x' (только его значение) чего хочет OP. –

5

Закрыть, но не совсем (работает только для одиночного выражения), что еще вопрос:

#define PRINT(fmt, var) printf(#var " = " fmt, (var)) 

Вот пример:

#include <stdio.h> 
#include <stdlib.h> 

#define PRINT(fmt, var) printf(#var " = " fmt, (var)) 

int 
main(int argc, char *argv[]) 
{ 
    int x = 2, y = 3; 
    float f = 4.6; 
    char c = 'A'; 
    char *str = "Bla bla"; 
    PRINT("%d\n", x); 
    PRINT("%f\n", f); 
    PRINT("%c\n", c); 
    PRINT("%s\n", str); 
    PRINT("%d\n", x+y); 
    exit(EXIT_SUCCESS); 
} 
+1

Это работает только для одной переменной. – Dipto

+1

@ Dipto Да, вы правы, и именно поэтому я сказал «близко, но не совсем» :-) –

+0

Typo: not * signal * but * single * variable! –

1

Я не думаю, что вы можете достичь того, чего вы хотите.

Но что-то подобное может быть вашим:

#define PRINT(fmt, val) fprintf(stderr, "%s=" fmt, #val, val) 

... 

int x = 2; 
float f = 4.6; 
char c = 'A'; 
char* str = "Bla bla"; 
// calling the macro: 
PRINT("%d ", x); 
PRINT("%f ", f); 
PRINT("%c ", c); 
PRINT("%s\n", str); 
1

Слегка, что вы можете:

#include <stdio.h> 

#define STRINGIFY(x) #x, (x) 
#define FPRINTF(file, fmt, ...) fprintf(file, fmt, __VA_ARGS__) 
#define PRINTF(fmt, ...) FPRINTF(stdout, fmt, __VA_ARGS__) 

int main(void) 
{ 
    int i = 42; 
    char ch = 'a'; 
    char str[4] = "alk"; 

    PRINTF("%s=%s, %s=%c, %s=%d\n", 
    STRINGIFY(str), 
    STRINGIFY(ch), 
    STRINGIFY(i) 
); 

    /* of just use printf directly: */ 
    printf("%s=%s, %s=%c, %s=%d\n", 
    STRINGIFY(str), 
    STRINGIFY(ch), 
    STRINGIFY(i) 
); 

    return 0; 
} 
1

/Надевает Индиана Jones` шляпу/

Я могу быть немного слишком поздно, но я должен сказать, что эта проблема имеет правильное (-иш) решение.

Во-первых, некоторые предварительные определяет (explanation here):

#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`s ответа:

#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], но его можно легко распространить на любой аргумент count, особенно на степени 2. Однако, чем больше аргументов он поддерживает, тем менее элегантным он выглядит.

P.S .: @BasileStarynkevitch уже предоставил все правильные ссылки, чтобы выяснить, как это работает.