0

I realize the following will not work but is there an equivalent?

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

What I want to do is concatenate strings and then make that concatenated string a static variable so that it becomes a global variable. Also I like not having to assign memory to a char. I need this to go in main() because I need to use a function (sprintf) to merge two strings.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user983223
  • 1,146
  • 2
  • 16
  • 32
  • 2
    You may use `##` operator in macro – Grijesh Chauhan Aug 01 '13 at 14:36
  • @alk - what about when there is a variable? So "_bar" is really a variable bar... – user983223 Aug 01 '13 at 14:42
  • 1
    Note that on a 64-bit machine, you've allocated 12 bytes to support `foo`: 8 bytes for the pointer and 4 bytes for the string. If you get something to work, you've got 16 bytes allocated for `end`: 8 bytes for the pointer, and 8 bytes for the string. You have to specify the 8 bytes for the string somehow. Note that using `const char foo[] = "foo";` only allocates 4 bytes for the string, and `const char end[] = "foo_bar";` only allocates 8 bytes for the string. – Jonathan Leffler Aug 01 '13 at 14:44
  • What do you want to express with this statment, please: "*Also I like not having to assign memory to a char.*" – alk Aug 01 '13 at 14:49

3 Answers3

1

sprintf is declared as int sprintf(char *str, const char format, ...); char* str is the buffer to which the output will be written, however malicious users might put more to that buffer than the sizeof that buffer therefore one can also use snprintf which includes a parameter that contains the size of the output buffer so bufferoverflows will not happen. What you should note it returns the number of bytes written, therefore you cannot assign it to a char or char[].

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

I prefer to use snprintf for it doesn't as easily result in a buffer overflow which is a security error. Now it can atmost print BUFSIZ characters to end you can look if the concatenation succeeded if snprintf returns strlen("s_bar") + strlen("foo");

What you can also do is:

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

which is perhaps more what you like.

hetepeperfan
  • 4,292
  • 1
  • 29
  • 47
1

Superficially, you could revise the code as follows:

#define FOO_INITIALIZER "foo"

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

I'm not sure how much it buys you, but it should compile and avoids repetition of the strings. It uses adjacent string literal concatenation, which is standard in C89 and later (but not in pre-standard compilers).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

I think you can do it with the stringizing operator.

#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;
}
abelenky
  • 63,815
  • 23
  • 109
  • 159
  • 2
    You can't use `##` to concatenate strings (or, at least, your compiler shouldn't let you do that) — and you don't need to do it because string concatenation happens automatically. – Jonathan Leffler Aug 01 '13 at 14:55
  • @JonathanLeffler: This was actually tested (MS VS2010). So I can do it. :) – abelenky Aug 01 '13 at 14:56
  • 2
    You need to get a working, standard-compliant compiler! GCC says `cat.c:3:1: error: pasting ""foo"" and ""_bar"" does not give a valid preprocessing token`. – Jonathan Leffler Aug 01 '13 at 14:56
  • http://ideone.com/khGkvF – abelenky Aug 01 '13 at 15:02
  • I'm not disputing that MSVC does allow it. I'm stating that the standard (ISO/IEC 9899:2011) says in §6.10.3.3 **The ## operator** _¶3 For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token. [...] If the result is not a valid preprocessing token, the behavior is undefined._ So, you're invoking undefined behaviour. – Jonathan Leffler Aug 01 '13 at 15:06
  • 3
    Using just `#` operators is fine, of course. The original macro was `#define CONCAT(x, y) #x ## #y` or equivalent. The revision is fine. – Jonathan Leffler Aug 01 '13 at 15:08