Returning direct and array function string

4

What works:

void *teste();

int main () {
    printf("\nRESULTADO: %s\n", teste());
    return 0;
}

void *teste(){
    return "Ponteiro";
}

What goes wrong:

void *teste();

int main () {
    printf("\nRESULTADO: %s\n", teste());
    return 0;
}

void *teste(){
    char p[10]="Ponteiro";
    return p;
}

Why the first of the right and the second not? How do I return a string allocated in a variable?

    
asked by anonymous 03.11.2017 / 15:11

2 answers

6

The first is returning a pointer to a static area of code that is always available. The text already exists inside the executable.

The second is returning a pointer to an area of the stack, which may or may not be available when the function terminates. At the end of it there is an unstack, so all the content that was in the stack when this function was running can no longer be accessed, so an attempt to access that area is an error (although by coincidence it might be possible if the data has not yet been deleted, but you should not trust it ever.)

Note that even in the second example there is text in the static area to play in the p variable. When you run the line there the static area content is copied to the stack and p has the address of that area, not static.

Arrays are types by value and therefore their value is in the storage area where it was declared. The local variable is its storage location.

You can only access an object outside a function where it was created if it is in the static area already present in the code or in heap , where you are responsible for #

Understand What are and where are the stack and heap? .

When you have to receive text that comes from a function, the correct one is to allocate the memory in the function that is going to use and pass the address of this allocated place to the function that will generate the text, so this function has all the responsibility of allocating and free up memory. You should always do so. All philosophy of C is on top of this.

There are those who think that a lot of code and the allocation should go in the function that generates the text, but this is not suitable. It works on simple systems, but getting to do bigger things is too risky to have to manage allocation and release in different places.

If you use the text only there and it is guaranteed that it is not absurdly large you can allocate it in stack . So just declare the array and you do not need to release it because what is in the stack is automatically managed.

But there is a problem, this requires you to make a copy of the text. If it's small okay, if it's large it's not efficient. The solution given in the other answer does not work in all situations and has compiler that does not even compile.

So almost always the solution is to allocate in heap .

I made an example of the wrong way to allocate memory in the heap within the function that generates the text and let anyone calling this function worry about the release. But that leaves room for the person to forget to do or do at the wrong time, creating serious problems. You are responsible for managing the lifetime of the heap object. So it's best to always pair with malloc() and free() .

As the dynamic allocation in heap can fail you have to check if it worked before doing anything in this memory location.

I also copied because to work in any situation. So in this case it is not efficient either.

So what's the solution? The first example of the question is the best way in most cases because it only takes text that is already in static area efficiently. It will only be a problem if you need to change this value. You can not move the static area, just copying. Most of the time you do not have to move.

I would only change the type of return to char * .

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

void teste(char texto[10]) {
    strcpy(texto, "Ponteiro"); //isto não é seguro, mas sabemos que funciona neste caso
}

char *teste2() {
    char *texto = malloc(10);
    if (texto != NULL) strcpy(texto, "Ponteiro"); //neste caso dá para eliminar isto, deixei porque o normal é fazer assim
    return texto;
}

int main () {
    char texto[10];
    teste(texto);
    printf("\nRESULTADO: %s\n", texto);
    //segunda forma não recomendada
    char *texto2 = teste2();
    if (texto2 != NULL) {
        printf("\nRESULTADO: %s\n", texto2);
        free(texto2); //tem que librar a memória que foi alocada por outra função
    }
}

See running on ideone . And no Coding Ground . Also put it in GitHub for future reference .

See more at:

03.11.2017 / 15:22
2
  

Why the first one right and the second not?

The first one works fine because when your program runs it first allocates a space for this constant string , and stores that value in that space. So when it runs return "Ponteiro"; it already knows the address of this constant string and returns that address.

The second does not work, because when the void *teste() function finishes executing, what has been allocated within its scope is deallocated (except what is allocated in heap - malloc / calloc ).

  

How do I return a string allocated to a variable?

I'll give you two examples of how to do this, first the and the other using heap ( malloc / calloc )

Using the Stack

void *teste(char *p);

int main () {
    char p[10];
    printf("\nRESULTADO: %s\n", teste(&p));
    return 0;
}

void *teste(char *p){
    p ="Ponteiro";
    return p;
}

It is guaranteed that this will work, because char p[10]; will only be deallocated when main() is finished, that is, I will already have done everything I wanted with the variable before it was deallocated.

Using Heap

void *teste(char *p);

int main () {
    char *p = (char *) malloc(sizeof(char)*10);

    if(p == NULL) {
        printf("Não foi possivel alocar 10bytes para o array p");
        return -1;
    }

    printf("\nRESULTADO: %s\n", teste(p));
    free(p);
    return 0;
}

void *teste(char *p){
    p ="Ponteiro";
    return p;
}

Note that any one function can allocate and deallocate using malloc / free , so you can make your variable live longer than the end of any X function.     

03.11.2017 / 15:52