2013-08-01 33 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“”没有提供有效的预处理标记。 –