You are overcomplicating this so much that I just TL;DR.
Some remarks that you might surely want to read, learn, embrace well and use:
I. int
is not for string lengths and stuff. size_t
is for string lengths and stuff.
II. String literals cannot be modified, so using the legacy char *
type for assigning them to a variable is no good by any means, const
-qualify that poor pointer base type.
III. Use VLAs instead of malloc()
if dynamic memory management is not really needed (we're not living in 1989 anymore).
IV. NUL
-terminate your strings because C stdlib routines expect you to do so.
int main()
{
const char *in = "foo bar baz";
int nspc = 0;
for (const char *p = strchr(in, ' '); p; p = strchr(p + 1, ' '))
nspc++;
char buf[strlen(in) + nspc * 2 + 1];
memset(buf, 0, sizeof(buf));
const char *s = in;
for (const char *p = strchr(s, ' '); p; p = strchr(s, ' ')) {
strncat(buf, s, p - s);
strcat(buf, "___");
s = p + 1;
}
const char *end = in + strlen(in);
strncat(buf, s, end - s);
printf("%s\n", buf);
return 0;
}