2015-08-19 4 views
2

Почему использование скобок в первом коде работает, а второе - нет?Разница между переменными параметрами с круглыми скобками и без них

В первом коде я использую только переменный параметр с круглыми скобками, а второй имеет параметр Integer с переменным, если я использую круглые скобки, когда я вызываю функцию, она не будет работать.

#include <bits/stdc++.h> 

void func(char* szFormat, ...); 

#define M1(a) M2(a) 
#define M2(b) func b 

int main() 
{ 
    M1(("Hello %s %d\n", "world",2015)); // this works 
    return 0; 
} 

void func(char* szFormat, ...) 
{ 
    char  trace_str[1000]; 
    va_list arg_list; 
    std::string str; 

    va_start(arg_list, szFormat); 
    vsprintf(trace_str, szFormat, arg_list); 
    va_end(arg_list); 

    str += trace_str; 
    std::cout << str << std::endl; 
} 

Этот код не работает, используя круглые скобки.

#include <bits/stdc++.h> 

void func(int year, char* szFormat, ...); 

#define M1(a,...) M2(a, __VA_ARGS__) 
#define M2 func 

int main() 
{ 
// M1(2015, ("Hello %s", "world")); // this doesn't works 
    M1(2015, "Hello %s", "world"); // this way works 
    return 0; 
} 

void func(int year, char* szFormat, ...) 
{ 
    char  trace_str[1000]; 
    va_list arg_list; 
    std::string str; 


    va_start(arg_list, szFormat); 
    vsprintf(trace_str, szFormat, arg_list); 
    va_end(arg_list); 

    str += trace_str; 
    std::cout << str << " " << year << std::endl; 

} 

Спасибо всем!

+1

Вы действительно использовать в с переменным числом аргументов ++? Никогда не видел этого в течение длительного времени ... – Klaus

ответ

2

Достаточно увидеть выход препроцесса, чтобы понять это.

входного файла:

void func(int year, char* szFormat, ...); 

#define M1(a,...) M2(a, __VA_ARGS__) 
#define M2 func 

int main() 
{ 
    M1(2015, ("Hello %s", "world")); // this doesn't works 
    M1(2015, "Hello %s", "world"); // this way works 
    return 0; 
} 

выход c++ -E foo.cpp:

# 1 "ess.cpp" 
# 1 "<built-in>" 1 
# 1 "<built-in>" 3 
# 155 "<built-in>" 3 
# 1 "<command line>" 1 
# 1 "<built-in>" 2 
# 1 "ess.cpp" 2 
void func(int year, char* szFormat, ...); 




int main() 
{ 
    func(2015, ("Hello %s", "world")); 
    func(2015, "Hello %s", "world"); 
    return 0; 
} 

Соответствующая часть здесь:

M1(2015, ("Hello %s", "world")); // this doesn't works 
    M1(2015, "Hello %s", "world"); // this way works 

    func(2015, "Hello %s", "world"); 
    func(2015, "Hello %s", "world"); 

Макрос интерпретируется только препроцессором. Если вы поместите два скобки, вы получите один дополнительный вызов функции, и он не даст ожидаемого результата. Здесь компилятор просто увидит оператор запятой во внутреннем блоке, увидит оценку пустоты или "Hello %s", а затем "world", и он закончится func(2015, "world");. Но func(2015, ("Hello %d", 12)); закончится func(2015, 10); с ошибкой синтаксиса не известно преобразованием из «Int» в «символ *» для 2-го аргумента


В первом коде, вы имели #define M2(b) func b что удалить один уровень круглых скобок, так

M1(("Hello %s %d\n", "world",2015)); 

был (правильно) препроцессором, как

func ("Hello %s %d\n", "world",2015); 
+2

", и компилятор обнаруживает это как синтаксическую ошибку." Это действительно действительный синтаксис. – newacct