4

I am trying to printf a simple string but I am not being able to.

#include <stdio.h>

int main(){
   char *word;
   scanf("%s", &word);
   printf("%s\n", word);
   return 0;
}
 

When I insert the word my code breaks.

It just stops the program execution but doesn't give me any error.

What am I doing wrong?

Braiam
  • 1
  • 11
  • 47
  • 78
  • 1
    If you don't mind using a non-standard extension available in some compilers, you can use `scanf("%ms", &word);` to let `scanf` allocate the memory. Just remember to `free(word);` afterwards. – Ted Lyngmo May 22 '21 at 20:21

8 Answers8

10

Problem 1: you need to allocate space for your word.

Problem 2: Your scanf() syntax is incorrect for a character array.

Problem 3: scanf("%s", ...) itself is susceptible to buffer overruns.

SUGGESTED ALTERNATIVE:

#include <stdio.h>

#define MAXLEN 80

int main(){
   char word[MAXLEN];
   fgets(word, MAXLEN, stdin);
   printf("%s", word);
   return 0;
}
paulsm4
  • 114,292
  • 17
  • 138
  • 190
3

word needs space - i.e. memory

So change

char *word;

to

char word[1000]; // Or some other value as appropriate

And to prevent buffer overruns use

scanf("%999s", word); // 1 character for null!

BTW - Do not need &

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
3

By char* word, you are creating a pointer to the string but not actually allocating memory for the string which is causing the code to break.

You can either use malloc to dynamically allocate memory or try something like char str[len] where len is the string length.

atprra
  • 114
  • 5
2

In C, you need to manage the memory yourself.

char *word just points to a random memory address. No memory has been allocated. When you go to write to it the operation system won't let you and you get a memory access violation.

You need to allocate a specific amount of memory to store the characters, and the terminating null byte. "Strings" in C are arrays of characters, plus a null byte to end it. C doesn't know how much memory has been allocated to a variable.

char word[101];
scanf("%100s", word);
printf("%s\n", word);

That's space for 100 characters, plus the null byte. And scanf is restricted to read only 100 characters so it does not try to access someone else's memory.

Finally, word is already a pointer. No need to take its address.

Schwern
  • 153,029
  • 25
  • 195
  • 336
2

word is an initialised pointer; you have provided no space into which scanf() can write.

Also &word has type char** where the %s format specifier requires a char*.

   char word[32] ;
   scanf("%31s", word);
   printf("%s\n", word);
Clifford
  • 88,407
  • 13
  • 85
  • 165
1

What am I doing wrong?

Other than in the program itself, the fundamental thing you're doing wrong is failing to compile with warnings enabled:

Why should I always enable compiler warnings?

If you were to compile your program with warnings enabled, you would get something like:

source>:5:12: warning: format '%s' expects argument of type 'char *', but argument 2 
has type 'char **' [-Wformat=]
    5 |    scanf("%s", &word);
      |           ~^   ~~~~~
      |            |   |
      |            |   char **
      |            char *

See this on GodBolt.

That may not tell you what exactly the problem is, but it well direct you to where you're doing something fishy and unexpected.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
1

try this:

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

int main(void) {
  char buffer[80];
  fgets(buffer, sizeof(buffer), stdin);
  printf("echo %s\n", buffer);
  return 0;
}

In C you need to manage memory. In the example above we allocate a buffer of 80 bytes on the stack; asked the standard library to read up to 80 characters and then generated the output.

In your code snippet, you had an uninitialised pointer and then you where giving the address of that pointer (which is a stack address) to scanf. scanf will then proceed to read into your stack... which means that it will typically overwrite the return address of your function.

try this snippet:

int main(void) {
    char *buffer;
    printf("%p\n", &buffer); // This prints a stack address
}

I was looking for some reference that would explain the concept of clobbering the stack by writing into it. This was the top link I could find. https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions

When C calls a function, it will do the following:

  • push arguments into the stack
  • call the function which results in stack pointer and return address being pushed into the stack
  • push into the stack space for local variables (e.g. our char *word;) in your initial example.

On x86 stack grows up (i.e. to lower addresses) so when you write into the memory region of a local variable and you didn't reserve space for what you want to write you are effectively overwriting the call stack.

It helps to have an idea of how a to program a CPU with assembly, specially stack and function call / return in order to properly understand C. It is also extremely useful even when one is using higher order languages; sooner or later one needs to understand what is going on under all those layers of abstraction.

Pedro Marques
  • 2,642
  • 1
  • 10
  • 10
0
  1. Pointer is only the pointer and it does only hold the location of the object it points.
char *pointer;

This declaration creates the pointer which does not reference(point) anything.

You need to create an object and then assign the reference of this object to this pointer.

Examples:

char *word = malloc(100);
char array[100];
char *word = array;
  1. To scanf a string you need to have the pointer assigned with the reference of the ocject which is large enough to accommodate this string.
char *word = malloc(100);
scanf("%s", word);

The difference between word and &word is explained here: Quick question about check allocation function algorithm (C)

0___________
  • 60,014
  • 4
  • 34
  • 74