[Edit: Apperently the return value obtained from fgets is simply the address of the char buffer[SIZE] being used, so in my case it makes sense because I declared it locally (hence, block scope).. PS: Thanks for all the help!]
I just leant that the data stored by fgets doesn't stay the same once the compiler is done executing the function in which fgets is being invoked.
What's the reason behind this? Does the fgets' return data have a lifespan or something? If so, how did they even code a function such as fgets? Something that can keep track of the user's invocation scope?
Here's the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 10
void input_string (char** pptr_one, char** pptr_two)
{
char buffer[SIZE];
printf("\nInput: ");
char* x = fgets(buffer, SIZE, stdin);
//Copying the original fgets result address:
*pptr_one = x;
//Copying its contents to another variable:
*pptr_two = malloc(SIZE);
strcpy(*pptr_two, x);
}
int main (int argc, char **argv)
{
char* ptr_one;
char* ptr_two;
input_string(&ptr_one, &ptr_two);
printf("\nptr_one is pointing to: <%s>\n", ptr_one);
printf("ptr_two is pointing to: <%s>\n", ptr_two);
return 0;
}
CodePudding user response:
Your buffer char buffer[SIZE]
has automatic storage duration.
This means that after the function input_string()
returns, the memory associated with buffer
is freed and buffer
will cease to exist since it is a local variable.
Solution:
You could allocate memory for buffer
with malloc()
:
char *buffer = malloc(sizeof(char) * SIZE)
Or you could declare buffer
as static
:
static char buffer[SIZE];
CodePudding user response:
You (indirectly) set *pptr_one
to the address of buffer
, which stops existing when input_string
ends.
There's nothing special about fgets
; it just returns its first argument on success, which in this case is buffer
; afterwards, x
and *pptr_one
all point to the same piece of memory which is local to your function.
CodePudding user response:
void input_string (char** pptr_one, char** pptr_two)
{
char buffer[SIZE];
printf("\nInput: ");
char* x = fgets(buffer, SIZE, stdin);
// missing test for NULL return from fgets()
/*** DO NOT DO THIS.
* DO NOT TAKE THE ADDRESS OF A LOCAL VARIABLE FOR USE AFTER FUNCTION EXITS!
* When successful, fgets will return the address of 'buffer' so x points to buffer.
//Copying the original fgets result address:
*pptr_one = x;
*****/
//Copying its contents to another variable:
*pptr_two = malloc(SIZE);
// should check that malloc succeeded
strcpy(*pptr_two, x);
// Aren't you glad that fgets() guarantees buffer will be a null terminated string?
// Be sure caller free's the allocated piece of heap storage!
}
Or, if you want to use that info, make buffer static...
static char buffer[SIZE];
printf("\nInput: ");
Do NOT free the address if using a static block of memory.
Reviewing the OP, you wrote this: "I just learnt that the data stored by fgets doesn't stay the same once the ... [execution of] the function in which fgets is being invoked.
"
All data has a duration. Some is the duration of a file on disk, some is the entire duration of a program's execution, some is the fleeting duration of a function call.
Your 'buffer' evaporated when input_string()
ended and returned to its calling function ('main()'). Another way to hang onto the data is to define it in main()
and pass the buffer AND its length to input_string()
.
void input_string( char *buf, size_t len ) {
fgets(buffer, len, stdin);
}
int main() {
char buffer[ SIZE ];
input_string( buffer, sizeof buffer );
printf( "Got '%s' from stdin\n", buffer );
}
Above, input_string()
finished, but the data was still available.