-1

I have the following multiple-choice question and I cannot figure out why (A) and (C) are incorrect, any explanation would be appreciated! The only correct answer in the following question is (B).

Which of the following is a correct usage of scanf?
(A) int i=0; scanf("%d", i);
(B) int i=0; int *p=&i; scanf("%d", p);
(C) char *s="1234567"; scanf("%3s", &s);
(D) char c; scanf("%c", c);

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Nuggets10
  • 81
  • 5
  • 4
    Have you read the [reference](http://en.cppreference.com/w/cpp/io/c/fscanf)? – UnholySheep Dec 08 '16 at 08:36
  • `scanf` needs to modify variables by accessing memory. It needs an address to do it. So think in which examples it actually gets passed a valid address. – StoryTeller - Unslander Monica Dec 08 '16 at 08:41
  • Are there any cases where the ampersand or reference is not necessary? I feel like I have seen examples omitting the & but maybe I'm wrong. I thought references were only necessary for strings and arrays for some reason.. – Nuggets10 Dec 08 '16 at 08:43
  • References do not exist in C. You have addresses and pointers, which basically are variables that hold an address. – Bart Friederichs Dec 08 '16 at 08:45
  • You don't need `&` when the argument is a string (e.g. `%s`), because arrays automatically become pointers when passed as function arguments. – Barmar Dec 08 '16 at 08:57
  • 2
    @UnholySheep you refer to the C++ documentation, better might be to use http://en.cppreference.com/w/c/io/fscanf – Bart Friederichs Dec 08 '16 at 09:59

5 Answers5

4

scanf wants a correct address where to store the result:

(A) int i=0; scanf("%d", i);

i is passed here by value, no address: wrong.

(B) int i=0; int *p=&i; scanf("%d", p);

p is a pointer to int, scanf can store its result here: right

(C) char *s="1234567"; scanf("%3s", &s);

&s is the address of a pointer to char *, you cannot store a string there: wrong

(D) char c; scanf("%c", c);

c is passed by value, not an address: wrong

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
  • Thank you, makes a lot more sense now. Looks like I have to look into the scanf function more carefully. – Nuggets10 Dec 08 '16 at 08:47
  • 1
    Yes, and also into pointers and addresses. They can be daunting, but once you get the hang of it, they are very powerful. I have to say though, I have never actually used `scanf` (or its siblings) in a real-world project. – Bart Friederichs Dec 08 '16 at 08:49
3

You must pass a pointer to the function so that it knows where in memory to store the value. If you just pass by value, it will treat that as a memory address, and all hell breaks loose. So you use & to take a reference (i.e. the memory address) of your variable.

That's why A and D are wrong.

As for C, it looks right because you are supplying a pointer, but you are actually referencing that pointer. So scanf will write over the pointer itself, not the memory it points to.

If you had just supplied s, then we get into another no-no land. The pointer is to a string literal which you are not allowed to modify. However, if it was not a literal but an array using the literal as an initializer it would be okay, provided you didn't read in more data than it can store:

char s[] = "1234567"; scanf("%3s", s); /* this is okay */ 
paddy
  • 60,864
  • 6
  • 61
  • 103
  • Thank you! Great explanation for both questions. I was completely unaware (oops..) that a pointer was required in both A and D. – Nuggets10 Dec 08 '16 at 08:46
  • "If you had just supplied s, then we get into another no-no land. " very helpful thanks – JimLohse Dec 18 '19 at 16:06
1

Learn this:

int i=0; scanf("%d", i);

Expanation: what is the address of i variable? for that & operator gives the address of i variable. scanf() getting user input and store the values on that address.

char *s="1234567"; scanf("%3s", &s);

Explanation: In this case, you were assigning string to character pointer and that is located in code section. Main aim of this option is the we can not modify the code section. But in this case we are modifying pointer. so after that pointer point to the newly assigned address else it may entered wrong address then get segmentation fault. so we lost previously assigned string.

Kanji Viroja
  • 493
  • 1
  • 7
  • 17
0

For A:

(A) int i=0; scanf("%d", i);

This should be:

(A) int i=0; scanf("%d", &i);

Take a look at the signature of scanf()

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
0

scanf with a specifier as %d takes an input as the address of the location to be scanned.

With 1. you are giving the input as i which is wrong

With 2. you are giving the input as p which has the address of i .This is set during the initialization as int *p=&i. So this is correct.

With 3. the specifier is %s. This takes an input of the address at which to start storing the string. The input of s is an array and already contains the address. &s is wrong.

With 4. You are using specifier of %c which also takes the address of the location. So giving an input of c is wrong in this case, as to get the address of the location you need &c

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31