2013-06-12 63 views
1

在C++中,在系統調用中使用宏是否可能並且安全?以下面的代碼爲例:系統調用中的宏

#define WINX 54 
#define WINY 30 

int main() 
{ 
system("mode con lines=WINY cols=WINX"); 
... 

這樣工作,並在代碼中使用是否安全?或者我會不得不手動構建一個字符串?

回答

5

宏不會在字符串文字內部擴展。相反,你可以使用另一個宏擴展宏成字符串文字,並使用字符串字面串聯,以創建所需的字符串:

#define STR2(x) STR(x) 
#define STR(x) #x 

const char *cmd = "mode con lines=" STR2(WINY) " cols=" STR2(WINX); 
system(cmd); 

STR2擴展提供的參數(如WINY)到它被定義爲然後將其傳遞給STRSTR只是使用字符串化宏操作符,其結果是字符串文字。在代碼被標記並編譯成目標代碼之前,相鄰的字符串文字被編譯器連接成單個字符串。

如果宏比簡單的數字更復雜,那麼你需要手動構造一個字符串。在C++中,最簡單的方法是使用ostringstream(從<sstream>):

std::ostringstream oss; 
oss << "mode con lines=" << WINY << " cols=" << WINX; 
system(oss.str().c_str()); 
+0

值得一提的是'STR2(WINY)'擴展爲字符串文字,相鄰的字符串文字在編譯的早期階段連接在一起。您可能還想提到,宏不在字符串文字內擴展,這就是爲什麼這種方法是必需的。 –

+0

預處理器在傳遞給系統之前不應該構造字符串,所以我應該能夠使用system(「mode con lines =」STR2(WINY)「cols =」STR2(WINX)); ? – user2403132

+0

@ user2403132:是的,但你必須告訴預處理器構造字符串;那就是''mode con con lines =「STR2(WINY)」cols =「STR2(WINX)''。 (你可以直接將它傳遞給'system()';'cmd'聲明並不是必須的。) –

3

宏確實不會在字符串中擴展。所以,這

system("mode con lines=WINY cols=WINX"); 

不會擴大到

system("mode con lines=30 cols=54"); 
0

你必須手動創建一個字符串。

例如:

char command[100]; 
int result; 
sprintf(command, "mode con lines=%d cols=%d", WINY, WINX); 
result = system(command); 

不要忘了要求包括指令:

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

請諮詢您的系統的文檔通過system返回的值的含義。

確保command陣列足夠大以容納完整的命令 - 或者,可能更好的是使用std::string代替。 jxh's answer顯示如何做到這一點。

+0

我想這對OP來說並不重要,但是在運行時沒有真正的理由這樣做。 – Lundin

+0

C++沒有定義在'std :: string'上工作的'sprintf'版本。 – jxh

+0

@jxh:我知道,我的意思是建議以其他方式構建一個'std :: string'。 [jxh's answer](http://stackoverflow.com/a/17073665/827263)顯示瞭如何做到這一點,並且比我的更好。 –

1

如果您不需要WINX和酒味的實際十進制值,您可以連接靜態的字符串,並在執行期間節省資源:

#define WINX "54" 
#define WINY "30" 

int main() 
{ 
system("mode con lines=" WINY " cols=" WINX);