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

相關問題