I am confused about some basics in C string declaration. I tried out the following code and I noticed some difference:
char* foo(){
char* str1="string";
char str2[7]="string";
char* str3=(char)malloc(sizeof(char)*7);
return str1;
/* OR: return str2; */
/* OR: return str3; */
}
void main() {
printf("%s",foo());
return 0;
}
I made foo() return str1/2/3 one at a time, and tried to print the result in the main. str2 returned something weird, but str1 and str3 returned the actual “string”.
1.Now, what’s the difference between the three declarations? I think the reason why str2 didn’t work is because it is declared as a local variable, is that correct?
2.Then what about str1? If the result remains after the foo() ended, wouldn’t that cause memory leak?
3.I’m simply trying to write a function that returns a string in C, and use the value returned by that function for other stuff, which str declaration above should I use?
Thanks in advance!
This makes
str1a pointer; it points to the first character of the string literal. You should define it asconst, because you’re not allowed to modify a string literal:…
This makes
str2an array ofchar(not a pointer), and copies the contents of the string literal into it. There’s no need to define it asconst; the array itself is writable. You can also omit the size and let it be determined by the initializer:Then
sizeof str2 == 7(6 bytes for"string"plus 1 for the terminating'\0').This:
is written incorrectly, and it shouldn’t even compile; at the very least, you should have gotten a warning from your compiler. You’re casting the result of
malloc()to typechar. You should be converting it tochar*:But the cast is unnecessary, and can mask errors in some cases; see question 7.7 and following in the comp.lang.c FAQ:
But
sizeof(char)is 1 by definition, so you can just write:malloc()allocates memory, but it doesn’t initialize it, so if you try to print the string thatstr3points to, you’ll get garbage — or even a run-time crash if the allocated space doesn’t happen to contain a terminating null character'\0'. You can initialize it withstrcpy(), for example:You have to be very careful that the data you’re copying is no bigger than the allocated space. (No, `strncpy() is not the answer to this problem.)
void main()is incorrect; it should beint main(void). If your textbook told you to usevoid main()find a better textbook; its author doesn’t know C very well.And you need appropriate
#includedirectives for any library functions you’re using:<stdio.h>forprintf(),<stdlib.h>forexit()andmalloc(), and<string.h>forstrcpy(). The documentation for each function should tell you which header to include.I know this is a lot to absorb; don’t expect to understand it all right away.
I mentioned the comp.lang.c FAQ; it’s an excellent resource, particularly section 6, which discusses arrays and pointers and the often confusing relationship between them.
As for your question 3, how to return a string from a C function, that turns out to be surprisingly complicated because of the way C does memory allocation (basically it leaves to to manage it yourself). You can’t safely return a pointer to a local variable, because the variable ceases to exist when the function returns, leaving the caller with a dangling pointer, so returning your
str2is dangerous. Returning a string literal is ok, since that corresponds to an anonymous array that exists for the entire execution of your program. You can declare an array withstaticand return a pointer to it, or you can usemalloc()(which is the most flexible approach, but it means the caller needs tofree()the memory), or you can require the caller to pass in a pointer to a buffer into which your function will copy the result.Some languages let you build a string value and simply return it from a function. C, as you’re now discovering, is not one of those languages.