Reputation: 23
I have the following problem: I need to read a string from stdin and must put it in an pointer. Then I must use this pointer as input for a function that isn't in the main function.
This is what I tried so far
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_LENGTH 50
void print (char*text)
{
printf("%c", *text);
}
int main (void)
{
char*keyboard;
fgets(keyboard, LINE_LENGTH, stdin);
print (*keyboard);
return 0;
}
Thank you very much for reading this and thank you very much for answering.
Upvotes: 0
Views: 401
Reputation: 26
Thinking more concretely about what is going on should help.
An object is a continuous set of bits in memory. A variable is a name which is associated with an object. A type is a more abstract idea which is associated with a variable, and can be "applied" to an object.
A pointer is a type which conveys the idea: "treat this object as a memory address". A pointer can further convey a type that can be applied to the object at that address.
Memory can be allocated in different ways in different areas (statically, on the stack, or in some managed area, etc.).
So, when you declared char*keyboard
in main()
, you instructed the compiler to allocate an object on the stack, with the size of a memory address (e.g. 32 bits for x86 or 64 bits for x86_64), and associate it with the variable name keyboard
. The value stored in that object will then be treated as an address when it is accessed through keyboard
. If that address is dereferenced using keyboard
, the (probably different) object at the address stored in the object associated with keyboard
will be accessed, and treated as a char
.
Here is a diagram to illustrate:
...
keyboard
-------[0x1234]---------
... \
... \
... v
-------------[?]------
...
If the object associated with keyboard
contains the value 0x1234
, then when it is treated as a char *
and dereferenced, the character at location 0x1234
will be accessed, shown as ?
.
fgets()
will write characters to memory, starting at the address provided as its first argument. So it could store up to LINE_LENGTH
characters, starting at the address stored in the object associated with keyboard
, in your code.
But no value has been assigned to keyboard
.
That means that the fgets()
call could write characters to an undefined location in memory.
If you want to write up to 50
characters somewhere, you first must establish a safe place to write them. You could do this by allocating 50 characters on the stack:
int main...
{
char buffer[50];
...
or allocating static space for them:
char buffer[50];
...
int main...
{
...
Or by allocating some space in managed memory for them:
int main...
{
char *buffer_ptr = malloc(50 * sizeof(char));
if (!buffer_ptr) ...
...
free(buffer_ptr);
You could then point keyboard
to that storage by assigning the address of the first character to it:
keyboard = &buffer[0];
/* or */
keyboard = buffer;
/* or for the malloc() example case: */
keyboard = buffer_ptr;
But in this case, you could probably just use buffer
or buffer_ptr
directly.
Thinking about it more concretely like this should hopefully clear up some confusion, but it might help to point out a couple more things:
Your print()
function takes a char *
argument, but your code passes a char
to it. This is because keyboard
, which is a pointer to a char
, has been dereferenced, yielding a char
.
If the intent is to print only the first character of the memory which has been written to by the fgets()
call, then either accessing that character and then passing it directly, or passing a pointer to it and dereferencing it
within print()
would work, but not both. If the intent is to print the entire string which has been read, then the pointer could be passed (without dereferencing it), but the format
argument passed to printf()
should contain %s
for the string, and a pointer to that string should be passed to be converted by it.
Upvotes: 0
Reputation: 26355
char *keyboard;
is an uninitialized pointer. It reserves no memory for a string.
printf("%c", *text);
would print the first character of a string. %s
is the format specifier for printing entire strings, and expects a char *
.
Try using an array, which automatically reserves memory on the stack. Arrays decay to pointers when passed to functions.
#include <stdio.h>
#define LINE_LENGTH 50
void print(char *text)
{
printf("%s", text);
}
int main(void)
{
char keyboard[LINE_LENGTH];
if (fgets(keyboard, LINE_LENGTH, stdin))
print(keyboard);
}
Upvotes: 1