简体   繁体   中英

What is the difference between scanf(“%d”, *p) and scanf(“%d”, p)?

Pointers are a new thing for me and I'm struggling to understand it, but I won't give in and hopefully learn it.

What would be the difference between scanf ("%d", *p) and scanf ("%d", p) ?

In examples I saw that if I want to input some value in a variable, I should use scanf ("%d", p) . That doesn't make sense to me. Shouldn't it be scanf ("%d", *p) ?

I interpret it as: "put some integer value where the pointer is pointing" and for instance it is pointing on variable x and then it should be x = 10 , but it isn't. And how then to use scanf() and pointers to set values in an array?

Where and what am I getting wrong? I'm trying to learn this using C language, since it is the one which I'm supposed to use in my class.

For example:

#include <stdio.h>
int main () {
    float x[10], *p;
    int i;
    p = &x[0];
    for (i = 0; i < 10; i++) {
        scanf("%d", p + i);
    }
    for (i = 0; i < 10; i++) {
        printf("%d", *(p + i));
    }
    return 0;
}

Why is only p + i in the first for () {} and *(p + i) in the second loop? I would put *(p + i) also in the first for () {} . *(p + i) to me is like: "to what the (p+i)th element is and make it equal some value".

*p means go to the place p points to
&p means take the address of p , or "get a pointer to" p

int i;
scanf("%d", &i); // gives scanf a pointer to i

int i;
int *p = &i;
scanf("%d", p); // a more contrived way to say the same thing

The obligatory visual explanation is Pointer Fun with Binky .

You can read the types from right to left:

int *p => " p has type int * " => p is a pointer to an int
int *p => " *p has type int " => *p is the int pointed to by p

One is right, the other is wrong. (Or both may be wrong, depending on what p is.)

If you call

scanf("%d", SOMETHING);

then SOMETHING must be a pointer to an int .

If you have an int object, use unary & to get its address (ie, a pointer to the object):

int n;
scanf("%d", &n);

If p happens to be an int* , then you can use its value:

int *p;
scanf("%d", p);

But here I haven't assigned a value to p , so this compiles but has undefined behavior. This is ok:

int n;
int *p = &n;
scanf("%d", p);

As for using *p , that would be valid only if p is a pointer to a pointer to an int :

int n;
int *p0 = &n;
int **p = &p0;
scanf("%d", *p);

But it would rarely make sense to do that. The vast majority of the time, the argument is going to be simply the address of some int object, like &n .

If n is an int, then just passing n to scanf wouldn't make sense. You'd merely be passing the current value of n . The point is that you want to permit scanf to store a new value in n , and to do that, scanf need's the address of n .

Function calls in C pass arguments by value, not by reference. This means that when you call a function with arguments, the function receives copies of the arguments, and that function cannot directly modify the original arguments from the callsite. That is:

int x = 42;
foo(x);
printf("%d\n", x);

foo cannot change the variable x , and the code will always print 42 .

But there are many cases where a function might want to modify the arguments from the caller. scanf is one such case. To accomplish this, these functions require using a level of indirection . Instead of passing the variable to be modified directly to the function, the caller instead passes a pointer to that variable. The function then receives a copy of the pointer, and by dereferencing it, can access and can modify the variable it's pointing to.

I recommend spending some time reading the comp.lang.c FAQ. This topic is discussed in:

If p is the variable (say, an int), you would use &p to pass its pointer to scanf. p alone is not a pointer, and *p compounds the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM