Each function can return its own type, but it cannot return a pointer to memory allocated within its function stack because the function stack is released for reuse on the function return and is no longer reachable. Any attempt to access a value whose memory is no longer reachable is Undefined Behavior.
You have two options, either (1) pass saida
as a parameter to text
, (e.g. char *text (char *s) { strcpy (s, "tata"); return s }
(the function could be declared void
at that point because the characters copied to s
will be available back in the caller anyway -- and there would be no need for strcpy
in main()
), or (2) dynamically allocate memory to hold "tata"
in text()
and return a pointer to the new block of memory. Memory allocated with malloc, calloc, or realloc
survives the function return as it is allocated on the heap and has program duration (or until it is freed).
(note: a 3rd option is to declare palavra1
as a static
character array of sufficient size to hold "tata"
-- which would also cause it to survive function return. However that practice should generally be avoided in favor of the first two options)
You could dynamically allocate in a simple fashion like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *text(void)
{
char *p = "tata", /* delcare pointer to string literal "tata" */
*palavra1 = malloc (strlen (p) + 1); /* allocate storage */
if (palavra1 != NULL) /* validate malloc succeeded */
strcpy (palavra1, p); /* copy "tata" to palavra1 */
return palavra1;
}
int main(void)
{
char saida[50],
*p = text(); /* must preserve pointer to beginning of memory */
/* validate p not NULL and length < 50 */
if (p != NULL && strlen (p) < sizeof saida) {
strcpy (saida, p); /* copy to saida */
printf ("%s\n", saida); /* output */
free (p); /* free allocated memory */
}
return 0;
}
Example Use/Output
$ ./bin/allocinfn
tata
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind
is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/allocinfn
==13720== Memcheck, a memory error detector
==13720== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==13720== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==13720== Command: ./bin/allocinfn
==13720==
tata
==13720==
==13720== HEAP SUMMARY:
==13720== in use at exit: 0 bytes in 0 blocks
==13720== total heap usage: 1 allocs, 1 frees, 5 bytes allocated
==13720==
==13720== All heap blocks were freed -- no leaks are possible
==13720==
==13720== For counts of detected and suppressed errors, rerun with: -v
==13720== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
(also note: The proper declarations for main
are int main (void)
and int main (int argc, char **argv)
(which you will see written with the equivalent char *argv[]
). note: main
is a function of type int
and it returns a value. See: C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570). See also: See What should main() return in C and C++?)
Look things over and let me know if you have further questions.