2015-08-19 67 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

你真的使用可变参数在C++?从来没有见过很长一段时间...... – 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);结束与一个语法错误从“诠释”没有已知的转换“的char *”的第二个参数


在第一个代码,你有#define M2(b) func b是删除了一个括号水平,所以

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

是(正确)预处理为

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

“,编译器将其检测为语法错误。”这实际上是有效的语法。 – newacct

相关问题