1

Why doesn't this code return the expected concatenated string, but a 2?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char * meh() {
    char meh1[32] = "This ";
    char meh2[32] = "should work :)";
    return strcat(meh1, meh2);
}

int main() {
    printf(meh());
    return 0;
}
6
  • 4
    Are you joking: printf(meh()); ? Where did you read that? Commented Dec 13, 2014 at 19:50
  • 2
    Don't return local variables (strcat() returns meh1) to calling code. Don't use printf() like that: use printf("%s\n", meh());. Returning a (pointer to) a local variable is a recipe for disaster; you get undefined behaviour, which means that the program can do almost anything and whatever happens is OK because there is no requirement on the compiler to do anything sensible with undefined behaviour. Commented Dec 13, 2014 at 19:52
  • @Jonathan I'm pretty sure he posted both the expected and the actual result. Commented Dec 13, 2014 at 19:54
  • 1
    Continuing with what Jonathan Leffler said, the form printf(meh()); could lead to an Uncontrolled format string vulnerability if meh() returns a string formed from user supply input, more information here: en.wikipedia.org/wiki/Uncontrolled_format_string#Details Commented Dec 13, 2014 at 21:03
  • I know that my previous comment is not that helpful, given the nature of the question. But it won't do any harm to highlight the dangers ahead of you. Commented Dec 13, 2014 at 21:09

4 Answers 4

5

Because once you leave function meh, meh1 goes out of scope and the area it occupied on the stack is used for other things inside of printf.

Sign up to request clarification or add additional context in comments.

3 Comments

That doesn't solve OP's problem! He only knows what it is now!
The OP's question was "why?" not "how do I fix?" - he-or-she is probably on the verge of a conceptual breakthrough of how local variables work and just needs a push in the right direction.
okay agree with you! But i think it would be still helpful to see a working example for OP!
2

Since strcat() writes into its first argument, you actually return a pointer to (the first element of) meh1. meh1 and meh2 are variables with automatic storage duration. Once the surrounding function returns, these variables are destroyed. Access to them produces undefined behaviour (usually a crash).

Here is what you could do:

const char *meh(void)
{
    char meh1[32] = "This ";
    char meh2[32] = "should work :)";

    char *result;
    size_t meh1_len, meh2_len;

    /* figure out how long meh1 and meh2 are */
    meh1_len = strlen(meh1), meh2_len = strlen(meh2);

    /* make a new string with enough space */
    result = malloc(meh1_len + meh2_len + 1);
    if (result == NULL)
        perror("Cannot malloc");

    /* Copy the strings */
    memcpy(result, meh1, meh1_len);
    memcpy(result + meh1_len, meh2, meh2_len + 1);

    return (result);
}

Don't forget to call free() on the result of meh() once you don't need it anymore.

4 Comments

It looks like small typo, should be meh1_len = strlen(meh1), meh2_len = strlen(meh2);. +1 anyway for pointing out UB :-)
@GrzegorzSzpetkowski Fixed the typo.
I read the other comments but I couldn't understand it 100%, but this snippet worked. I'm beggining with C and I have so much to learn, thanks for this piece of code.
@FilipeTeixeira Always remember: C does nothing for you. You have to do all the things yourself!
2

strcat modifies the string meh1 by appending the string meh2, it then returns a pointer to the first string. The string meh1 is declared in the function, so the pointer is invalid outside of the function. This is why you don't get the resut you expect. Instead, you could do something like this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void meh(char * meh1) {
    char meh2[32] = "should work :)";
    strcat(meh1, meh2);
    return;
}

int main() {
    char meh1[32] = "This ";
    meh(meh1);
    puts(meh1);
    return 0;
}

This will give the expected result. It works because the string meh1 is declared in main and then passed to the function to be modified. This means that the modified string is still available in main after the function call to meh.

1 Comment

This works in this scenario because the variables are big enough (meh1 in particular is big enough to hold the string that results from the concatenation). However, the function meh() has no way of verifying that it is OK. It doesn't know how big the destination string is. Consequently, there's no point in it checking the initial length of the string in the destination string, or the length of the string to be added, but resilient code would be told how much space there is (e.g. void meh(char *buffer, size_t buflen) and it then would check that the result string fits in the buffer.
0

From the man page of strcat(),

char *strcat(char *dest, const char *src);   

and

The strcat() and function return a pointer to the resulting string dest.

As per your usage, dest is the base address of char meh1[32], which is local to meh(). Once the control returns from the meh(), the meh1 goes out of scope. So, the result of printf() is undetermined [undefined behaviour].

To make it work, use pointers and dynamic memory allocation for meh1.

For example,

char *meh1 = NULL;
meh1 = malloc(32);
strcpy(meh1, "this");

and the rest of existing meh().

The dynamically allocated pointer can be returned as per your requirement. At the end of main(), you need to free() the returned pointer to avoid memory leak.

Also, you need to use printf() like

 printf("%s\n", meh());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.