1

I'm trying to figure out why C does this. It's a very simple string concatenation code but I get very different outputs depending on what goes into strcat.

Can someone shed some light on this?

// With all declared variables
char * hello = "HELLO";

char * world = "WORLD";

char * space = " ";

char * say_hello(){
  char * out = "";
  strcat(out,hello);
  strcat(out,space);
  strcat(out,world);
  return out;
}

main(){
   puts(say_hello()); 
}

// outputs "HELLO WORLD"
// With all hello as declared variable

char * hello = "HELLO";

char * say_hello(){
  char * out = "";
  strcat(out,hello);
  strcat(out," ");
  strcat(out,"WORLD");
  return out;
}

main(){
   puts(say_hello()); 
}

// outputs "HELLOELLOLOELLO"
// With all hello and world as declared variable

char * hello = "HELLO";

char * world = "WORLD";

char * say_hello(){
  char * out = "";
  strcat(out,hello);
  strcat(out," ");
  strcat(out,world);
  return out;
}

main(){
   puts(say_hello()); 
}

// outputs "HELLOELLOWORLD"
// With all constants

char * say_hello(){
  char * out = "";
  strcat(out,"HELLO");
  strcat(out," ");
  strcat(out,"WORLD");
  return out;
}

main(){
   puts(say_hello()); 
}

// outputs "HELLO WORLD"
zcaudate
  • 13,998
  • 7
  • 64
  • 124
  • You can't safely use `strcat` with a pointer like that; you'll need to specify the length of `out`... – AKX Jun 10 '21 at 14:15
  • You also can't return a pointer to a pointer on the stack such as your `char *out`. – AKX Jun 10 '21 at 14:16
  • 5
    You really should read the chapter dealing with strings in your C text book. – Jabberwocky Jun 10 '21 at 14:16
  • 1
    In C, if you cannot explain in detail what your pointer is pointing to, how big that area is and what gives you the right to write there ... your code is wrong 99 out of a 100 times. – Yunnosch Jun 10 '21 at 14:18
  • I get that it's dangerous code. I'm trying to figure out why something like these examples occurs, ie, Is it to do with how the pointers are laid out in memory etc... For instance, the "HELLOELLOLOELLO" returned via the second case is not random, but consistently the same - so it's not undefined behaviour in the strict sense. – zcaudate Jun 11 '21 at 07:00

1 Answers1

8

All of the code are invalid and dangerous.

First of all, modifying string literal is prohivited and trying to do so invokes undefined behavior. strcat will modify the string passed as the first argument, so you must not pass string literals (or pointers pointing at string literals) there.

Secondly, "" is one-element array {'\0'}. It is not capable to store the string created by concatination. You have to allocate enough space.

Note that life of non-static local array ends on returning from the function, so you have to allocate eithor dynamically or statically.

Dynamic allocation:

#include <stdlib.h>

char * say_hello(){
  char * out = calloc(32, sizeof(*out)); /* allocate */
  if (out == NULL) exit(1); /* check if allocation succeeded */
  strcat(out,hello);
  strcat(out,space);
  strcat(out,world);
  return out;
}

Static allocation (warning: this is not thread-safe):

char * say_hello(){
  static char out[32];
  out[0] = '\0';
  strcat(out,hello);
  strcat(out,space);
  strcat(out,world);
  return out;
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70