C string declaration

I got confused in some basics in the declaration of line C. I tried 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 did foo () return str1 / 2/3 one at a time and tried to print the result in main. str2 returned something strange, but str1 and str3 returned the actual "string".

1. Now, what's the difference between the three ads? I think the reason str2 doesn't work is because it is declared as a local variable, is that correct?

2. What about str1? If the result remains after the end of foo (), will this lead to a memory leak?

3. Am I just trying to write a function that returns a string in C, and use the value returned by this function for other things, which should be indicated in the str declaration above?

Thanks in advance!

+4
source share
3 answers
 char* str1="string"; 

This makes str1 pointer; it points to the first character of a string literal. You must define it as const , because you are not allowed to modify the string literal:

 const char *str1 = "string"; 

...

 char str2[7]="string"; 

This makes str2 a char array (not a pointer) and copies the contents of the string literal into it. There is no need to define it as const ; the array itself is writable. You can also omit the size and define it as an initializer:

 char str2[] = "string"; 

Then sizeof str2 == 7 (6 bytes for "string" plus 1 for the final '\0' ).

It:

 char* str3=(char)malloc(sizeof(char)*7); 

It is written incorrectly, and it does not even compile; at least you should get a warning from your compiler. You type the result of malloc() to enter char . You should convert it to char* :

 char *str3 = (char*)malloc(sizeof(char) * 7); 

But the throw is not needed and can mask errors in some cases; see question 7.7 and follow in the comp.lang.c FAQ :

 char *str3 = malloc(sizeof(char) * 7); 

But sizeof(char) is 1 by definition, so you can simply write:

 char *str3 = malloc(7); 

malloc() allocates memory, but it does not initialize it, so if you try to print the line pointed to by str3 , you will get garbage - or even crash at runtime if the allocated space does not contain the terminating null character '\0' . You can initialize it with strcpy() , for example:

 char *str3 = malloc(7); if (str3 == NULL) { fprintf(stderr, "malloc failed\n"); exit(EXIT_FAILURE); } strcpy(str3, "string"); 

You must be very careful that the data you copy is no more than the allocated space. (No, `strncpy () is not the answer to this problem .)

void main() invalid; it should be int main(void) . If your tutorial told you to use void main() find the best tutorial; its author does not know C. very well.

And you need the appropriate #include directives for any library functions that you use: <stdio.h> for printf() , <stdlib.h> for exit() and malloc() and <string.h> for strcpy() . The documentation for each function should indicate which title should include.

I know that it is a lot to devour; don't expect to understand everything right away.

I mentioned the comp.lang.c FAQ ; this is a great resource, particularly section 6, which discusses arrays and pointers and the often confusing relationships between them.

As for your question 3, how to return a string from a C function, which turns out to be surprisingly complicated because C makes memory allocation (basically it leaves to manage it yourself). You cannot 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 str2 is dangerous. The return of the string literal is fine, as this corresponds to an anonymous array that exists for the entire execution of your program. You can declare an array using static and return a pointer to it, or you can use malloc() (this is the most flexible approach, but that means the caller needs free() memory), or you can require the caller to pass a pointer to the buffer where your function will copy the result.

Some languages ​​allow you to build a string value and simply return it from a function. C, as you open now, is not one of these languages.

+8
source
 char* str1="string"; 

This creates a pointer to a literal string that will be located on .data or .text segments and is always available. Whenever you do something like this, be sure to declare it const , because if you try to change it, unpleasant things can occur.

 char str2[7]="string"; 

This creates a local buffer on the stack with a copy of the string. When a function returns, it becomes unavailable. This explains the strange result you get.

 char* str3=(char)malloc(sizeof(char)*7); 

This creates a buffer on the heap (uninitialized) that will be available until you free it. And free it, or you will get a memory leak.

+6
source

The string literal "string" is stored as a 7-element char array with a static degree, which means that memory is allocated for it when the program starts and is held until the program terminates.

Ad

 char *str1 = "string"; 

assigns the address of the string literal str1 . Despite the fact that the variable str1 ceases to exist when the function ends, its value (the address of the literal "string" ) remains valid outside the function.

Ad

 char str2[7] = "string"; 

declares str2 as a char array and copies the contents of the string literal. When the function exits, str2 ceases to exist, and its contents no longer make sense.

Ad

 char *str3 = (char*) malloc(sizeof(char) * 7); 

which can be simplified to

 char *str3 = malloc(sizeof *str3 * 7); 

allocates an uninitialized 7-byte memory block and copies its address to str3 . When the function exits, the str3 variable ceases to exist, but the memory pointed to by it is still allocated. As written, this is a memory leak because you are not storing the pointer value in the calling code. Note that since you are not copying anything to this block, the output in main will be random.

Also, if your compiler documentation does not explicitly list void main() as the legal signature for the main function, use int main(void) .

0
source

All Articles