2014-01-27 6 views
0
#define SEND_VALUE(num, point1, point2, point3...) \ 
{ \ 
    char number[6]; \ 
    char p1[6];\ 
    char p2[6];\ 
    char p3[6];\ 
    if(num == ONE) {sprintf(number, "ONE");}\ 
    if(num == TWO) {sprintf(number, "TWO");}\ 
    if(num == THREE) {sprintf(number, "THREE");}\ 
    if(point1 == ONE) {sprintf(p1, "ONE");}\ 
    if(point1 == TWO) {sprintf(p1, "TWO");}\ 
    if(point1 == THREE) {sprintf(p1, "THREE");}\ 
    if(point2 == ONE) {sprintf(p2, "ONE");}\ 
    if(point2 == TWO) {sprintf(p2, "TWO");}\ 
    if(point2 == THREE) {sprintf(p2, "THREE");\ 
    if(point3 == ONE) {sprintf(p3, "ONE");}\ 
    if(point3 == TWO) {sprintf(p3, "TWO");}\ 
    if(point3 == THREE) {sprintf(p3, "THREE");\ 
    fprintf(fp,"%s:%s:%s:%s:\n",number, p1,p2,p3);\ 
    fflush(fp); \ 
    fprintf(fp,fmt,##__VA_ARGS__);\ 
    fflush(fp); \ 
    fprintf(fp,"\n");\ 
    fflush(fp); \ 
} 

На данный момент этот макрос не требует переменности. Но для будущего использования я хочу, чтобы он был переменным. Я не знаю, как написать/определить список аргументов в переменном макросе и как их использовать. Как и в приведенном выше примере, p1, p2 следует установить и распечатать.Передача аргументов в переменный макрос

Я называю этот макрос так:

SEND_VALUE(ONE, ONE, ONE, ONE); 

Может кто-то пожалуйста, помогите в достижении этого VARIADIC путь?

+0

Вы имеете в виду способ, как это? http://stackoverflow.com/q/20499983/2003898 – dhein

+1

Вместо этого используйте переменную функцию. – this

+0

Я не знаком с переменными макросами. Может ли кто-нибудь сделать вышеупомянутый код вариативным и опубликовать его здесь? – aod

ответ

1

Предполагая, что вы также получаете fmt в качестве макро-параметра, здесь значительно сокращенный вариант макроса:

#define SEND_VALUE(num, point1, point2, point3, ...) \ 
do { \ 
    fprintf(fp,#num":"#point1":"#point2":"#point3":\n");\ 
    fflush(fp); \ 
    fprintf(fp,__VA_ARGS__);\ 
    fflush(fp); \ 
    fprintf(fp,"\n");\ 
    fflush(fp); \ 
} while(0) 

Если вы хотите быть явным с форматом, вы также можете сделать:

#define SEND_VALUE(num, point1, point2, point3, fmt, ...) \ 
do { \ 
    fprintf(fp,#num":"#point1":"#point2":"#point3":\n");\ 
    fflush(fp); \ 
    fprintf(fp,fmt,##__VA_ARGS__);\ 
    fflush(fp); \ 
    fprintf(fp,"\n");\ 
    fflush(fp); \ 
} while(0) 

, но вы должны отметить, что ,##__VA_ARGS__ является расширением gcc.

Несколько примечаний:

  • Использование do { } while(0) для макросов, которые расширяют для блоков кода, чтобы быть дурака; они могут быть помещены как один оператор в блок if/while/etc, и они также могут принимать ; без каких-либо дополнительных затрат времени.
  • Используйте #param, чтобы получить строку, значение которой является именем параметра. В вашем примере SEND_VALUE(ONE, ONE, ONE, ONE), #num будет "ONE".
  • В C "some"" string" эквивалентно "some string".
  • Было бы лучше, если бы вы передали fp в качестве параметра для макроса.

Edit: в конце концов, макрос может быть использован, как это:

SEND_VALUE(ONE, ONE, ONE, ONE, ""); 
SEND_VALUE(ONE, TWO, ONE, THREE, "%d", 10); 
SEND_VALUE(THREE, TWO, ONE, TWO, "format string! %s %s", "param1", "param2"); 
+0

Я не уверен, что такое fmt. Получил код из другого места и попытался изменить. fmt - это ключевое слово или что-то в этом роде? Или просто принимающая переменная, такая как point1, point2? И что делает fprintf (fp, fmt, ## __ VA_ARGS__); делать? – aod

+1

@aod, 'fmt' должен быть строкой формата. Ожидается, что 'fprintf (fp, fmt, ## __ VA_ARGS __)' будет расширяться до чего-то типа 'fprintf (fp,"% d% s ", x, str)' (предполагая мнимые параметры '"% d% d "', 'x',' str'). Если вы не понимаете, что делает 'fprintf', см. [Man page] (http://linux.die.net/man/3/fprintf). – Shahbaz