2

In the code below:

#include <stdio.h>

int main(){

  char *name;
  int age;  
  char *gen;

  printf("Your name:");
  scanf("%s",name);

  printf("Your age:");
  scanf("%d",&age);

  printf("Your gender:");
  scanf("%s",gen);

  printf("*****************\n");

  printf("%s is a %d years old %s \n",name,age,gen);

  return 0;  

}

When I run it like this:

Your name:tom
Your age:20
Your gender:male
*****************
tom is a 20 years old (null)

As you can see, gen is a null value, Why scanf fails reading into gen but the first two readings success?

user3289218
  • 87
  • 1
  • 5
  • 1
    so instead of char *name use char name[20] and char gen[20] – Rob Sep 10 '14 at 12:40
  • @Rob why `name` works without allocating memory to it but `gen` doesn't? – user3289218 Sep 10 '14 at 12:54
  • 2
    @user3289218 "luck". The worst symptom of Undefined Behaviour. – Quentin Sep 10 '14 at 12:55
  • 1
    You're in nasal demon territory, *anything* can happen. Oh, and there is no null value in your code (or at least, no value guaranteed to be null; on a Microsoft debug environment, it's guaranteed *not* to be). – Medinoc Sep 10 '14 at 12:58
  • 2
    Yep Quentin is right.. You were lucky the pointer to name did not point to something vital. you basically wrote somewhere in memory, you could have written to un-allocated memory or corrupted another variable somewhere or messed up instructions for a function.. there is no way to know. Hence your code's behavior is undefined. – Rob Sep 10 '14 at 13:05

2 Answers2

8
char *name;
char *gen;

are just char pointer and point nothing. So need to allocate memory for it.

You can allocate memory for it like

char *name = malloc(100);
char *gen  = malloc(100);

OR define char array with predefined length

char name[100];
char gen[100];
Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73
  • 1
    Do you mean that I need to specify the length of the char array, like `char name[10]`? – user3289218 Sep 10 '14 at 12:41
  • 1
    why does the name pointer works then, i tried swapping the scanf to read gen first, then name string went null. – Haris Sep 10 '14 at 12:41
  • @ralph This look me undefined behaviour. – Jayesh Bhoi Sep 10 '14 at 12:46
  • but why do I have to allocate memory for it first? – user3289218 Sep 10 '14 at 12:46
  • @user3289218 Because these are pointer only, not pointed to any address. You have to first give address pointer to that pointer and using that these pointer traverse memory how much allocate for it. – Jayesh Bhoi Sep 10 '14 at 12:48
  • And without allocating memory for `name`, why it worked but `gen` doesn't. – user3289218 Sep 10 '14 at 12:49
  • @user3289218 This may happen because of `sizeof(char *)` is may `4/8` in your machine and it allow to store you `3` char plus one `null` character. So `tom` will passed. Now try with more character then see what happen. – Jayesh Bhoi Sep 10 '14 at 12:54
  • I tried with a very long string, `name` always works but `gen` never. Or we can say the first scan of chars always works but the second doesn't – user3289218 Sep 10 '14 at 13:02
  • @user3289218 The fact that your program "works" at all is a complete fluke, and should never be relied upon – Jayesh Bhoi Sep 10 '14 at 13:05
1
char *name;
char *gen;

Are pointer, you need either to change to array

char name[256];//256 is arbitrary ofc
char gen[256];

or to allocate memory with your pointer:

char *name = malloc(256 * sizeof(*name));
char *gen = malloc(256 * sizeof(*gen));

Note that if you allocate memory with malloc, it is a good habbit to check if the allocation failed:

if (name == NULL)
    return -1;
mantal
  • 1,093
  • 1
  • 20
  • 38
  • 2
    No need to type cast return of `malloc` and `sizeof(char)` always `1`. so no need for it. – Jayesh Bhoi Sep 10 '14 at 12:43
  • I think it is a go habbit to cast malloc result, also sizeof is not needed here but for everythings else it is and as OP seem to be new to C, I don't want to confuse him. But I'll edit with more explaination – mantal Sep 10 '14 at 12:45
  • but why do I have to allocate memory for it first? – user3289218 Sep 10 '14 at 12:47
  • @mantal: You might consider reading this: http://stackoverflow.com/a/605858/694576 then you perhaps agree with many that it's actually bad habbit to cast the result of malloc & friends. – alk Sep 10 '14 at 12:56
  • Regarding the redundant use of `sizeof(char)`: Doing so `char * name = malloc(256 * sizeof(*name));` makes sense. – alk Sep 10 '14 at 12:58
  • @alk I changed to sizeof(*name) thanks. But I'll let the cast because I still think it is better and also because after Jayesh edit, my answer is a bit redundant, it is better to show that you have more than one way to do things. – mantal Sep 10 '14 at 13:02
  • Yes, but I'm more convinced by this : http://stackoverflow.com/a/14879184/3057566 Especially by the pointer part (* instead of ** ...). – mantal Sep 10 '14 at 13:05