2013-08-01 35 views
0

我意識到以下將無法正常工作,但有沒有相當的?全局變量在主要連接?

const char *foo = "foo"; 
static char *end = sprintf ("%s_bar", foo); 

我想要做的是連接字符串,然後使該連接字符串一個靜態變量,使之成爲一個全局變量。另外我喜歡不必將內存分配給字符。我需要這個去main()因爲我需要使用一個函數(sprintf)來合併兩個字符串。

+2

您可以在宏中使用'##'運算符 –

+0

@alk - 什麼時候有變量?所以「_bar」實際上是一個變量條... – user983223

+1

請注意,在64位機器上,您已經分配了12個字節來支持'foo':指針爲8個字節,字符串爲4個字節。如果你得到了一些工作,你已經有16個字節分配給'end':指針爲8個字節,字符串爲8個字節。您必須以某種方式指定字符串的8個字節。請注意,使用'const char foo [] =「foo」;'只爲字符串分配4個字節,而'const char end [] =「foo_bar」;'僅爲字符串分配8個字節。 –

回答

1

sprintf被聲明爲int sprintf(char * str,const char format,...); char* str是寫入輸出的緩衝區,然而惡意用戶可能會將該緩衝區放在比該緩衝區的大小更多的地方,因此也可以使用snprintf,其中包含一個包含輸出緩衝區大小的參數,因此緩衝區溢出不會發生。你應該注意到它返回的是寫入的字節數,因此你不能將它分配給char或char []。

const char* foo = "foo"; 
static char end[BUFSIZE]; 
snprintf(end, BUFSIZE, ""%s_bar", foo); 

我更喜歡使用snprintf因爲它並不那麼容易導致緩衝區溢出這是一個安全的錯誤。現在它可以打印BUFSIZ字符到end如果snprintf返回strlen(「s_bar」)+ strlen(「foo」);則可以查看連接是否成功。

什麼你也可以做的是:

char end[BUFSIZE] = "foo_"; 
strncat(end, "_bar", BUFSIZ); 

這也許是更多你喜歡什麼。

+1

你想寫'char end [BUFSIZE] ...'? – alk

+0

@alk哎呀你編輯得挺對的;-) – hetepeperfan

1

從表面上看,可以按如下修改代碼:

#define FOO_INITIALIZER "foo" 

const char *foo = FOO_INITIALIZER; 
static char *end = FOO_INITIALIZER "_bar"; 

我不知道多少給你買了,但它應該編譯和避免串的重複。它使用相鄰的字符串連接,這在C89及更高版本中是標準的(但不是在標準的編譯器中)。

1

我想你可以用字符串化操作符來完成它。

#define STR_CONCAT(x, y)  #x#y 

static char *end = STR_CONCAT(foo, _bar); 

int main(void) 
{ 
    printf("%s", end); // prints out "foo_bar" 
    getchar(); 
    return 0; 
} 
+2

你不能使用'##'連接字符串(或者,至少你的編譯器不應該讓你這麼做) - 而且你不需要這樣做因爲字符串連接會自動發生。 –

+0

@JonathanLeffler:這實際上已經過測試(MS VS2010)。所以我可以做到。 :) – abelenky

+2

你需要得到一個符合標準的工作編譯器! GCC說'cat.c:3:1:錯誤:粘貼「」foo「」和「」_bar「」沒有提供有效的預處理標記。 –