问题
I'm trying to learn the benefits and shortcomings of different ways to get input from the console. I'm confused with scanf
. Why do I need to use use &favNumber
instead of favNumber
?
I understand that &favNumber
is the address location of favNumber
, but why is it done this way?
I feel like there's a type mismatch here where favNumber
is an int and I'm telling scanf
that it's a pointer to an int. I thought I wrapped my head around pointers but this is confusing me a bit. Any help would be appreciated. Thanks!
#include <stdio.h>
int main()
{
char userPrompt[100] = "What is your favorite number?";
int favNumber;
printf("%s", userPrompt);
scanf("%d", &favNumber);
printf("%d", favNumber);
return 0;
}
回答1:
When you call a function by value, the function gets a copy of the argument. Any changes to the argument in the function does not affect the value of the original variable.
void foo(int i )
{
i = 20; // The change is local to the function.
}
void bar()
{
int i = 10;
foo(i);
printf("i=%d\n", i); // i is still 10.
}
If you want a function to change the value of a variable, the function must use a pointer type and the calling function must use the address of the variable when calling the function.
void foo(int* i )
{
*i = 20; // The change is visible in the calling function
}
void bar()
{
int i = 10;
foo(&i);
printf("i=%d\n", i); // i is now 20.
}
This is why scanf
expects pointers and the calling functions must use the address of variables when calling scanf
. scanf
must be able to set the values of the variables.
回答2:
An &
sign is used to reference a value by its memory address. So when a reference is passed around the use of that reference modifies the value at the address the reference holds.
scanf
is basically just a function, if you are familiar with functions you will see that a parameter passed in to a function by value will be local to the function and any assignment to it will only change its value within the function(which does not answer the need of storing the "scanned" value in the passed variable). In case of scanf
it accepts a reference(in other words the location in memory of that value) so it can modify the value at that location and the "scaned" value can be stored in the variable of interest.
So to wrap it up what &favNumber
does is passing to scanf
the memory address of favNumber
variable which in it self is an int
, so an int
value is then written to that address and can be accessed by favNumber
.
回答3:
"How do you use scanf to get an int in C?"
– you don't. You use a saner approach (e.g. fgets()
+ strtol()
), because scanf()
is quirky and clumsy and hard to use correctly.
However, your question is apparently not about this; you are asking why you have to write scanf("%d", &favNumber);
when &favNumber
is an int *
but %d
specifies an int
.
Well, you seem to be confusing type safety/type mismatches with arbitrary denotation of types expected by library functions.
&favNumber
is indeed a pointer to int. However, the %d
specifier does NOT mean that "you must pass an int
for this argument". %d
is a library-defined notation that tells scanf()
to scan an integer, and put it into the next argument. In order scanf()
to be able to modify your argument, you need to pass a pointer to it, and indeed this function expects that you pass a pointer to it.
I could put it this way: "%d"
simply means something different when used with printf()
and scanf()
: in the former case, it means you pass an int
argument, in the latter case, it means you should pass an int *
.
Again, that is the case because these format strings have no inherent semantics. It's the formatted input/output functions that interpret them – in this case, they interpret format strings differently for technical necessity reasons.
回答4:
Alright so what I believe you're confusion is coming to is the fact that '&' denotes an address, not a pointer to an address as '*' denotes but an address itself. You re telling the scan function where it will store the value that is received from the user. If you were to reference the variable itself ie 'favNumber' how would you know where to store the value that you've placed into stdin? favNumber is just a container, it's nothing special but just a place in memory that is allocated to hold said amount of bytes. I feel as if I understand where your question is coming from, but if you've already encountered pointers, I think you may be confusing the two. A pointer points to an address in memory, the '&' denotes the actual address, and does roughly what a pointer would do, but to a non pointer variable. If favNumber were a 'int *' type then you would not need the ampersand, as that is already an address, but you would need to dereference that address to be able to tell what is within it. That is roughly what you have within favNumber, a dereferenced address pointer that shows what is stored in the address of favNumber, that is allocated at the beginning of your program being run, in the stack.
来源:https://stackoverflow.com/questions/33717059/how-do-you-use-scanf-to-get-an-int-in-c