What is the difference between scanf("%d", *p) and scanf("%d", p)? - c

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 (i.e., 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:
12.12a Why doesn't the call scanf("%d", i) work?
12.12b Why does the call scanf("%s", s) work?

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.

Related

How to assign a value from an address to a pointer on the go?

Causes a segmentation fault:
int n;
int *variable = scanf("%d",&n);
printf("Printing :%d",*variable);
No problem:
int n;
scanf("%d",&n);
int *variable = &n;
printf("Printing :%d",*variable);
How to achieve the first one without the segmentation fault?
Assuming scanf was successful, it returns 1 (in general it returns the number of variables that were set).
In your second snippet you discard that (useful) information, and you are setting a pointer varaible to the address of n, which is perfectly valid. (If scanf returned 0 then n would be uninitialised, and the behaviour of your printf call undefined.)
In the first snippet you set a pointer to the int constant 0 or 1 depending on the return value of scanf. That's fine too, but the behaviour on dereferencing that pointer with
*variable
is undefined.
If you want to be flashy, and have a robust conversation with your code reviewer, you could use the expression separator operator and write
int n;
int *variable = (scanf("%d",&n), &n);
but that's naughty since, again, you discard the return value of scanf, and n could be uninitialised.
scanf("%d",&n); returns integer not pointer to integer. Below is the prototype of scanf.
int scanf(const char *format, ...);
When you point like below you are actually pointing to invalid address and it will lead to undefined behavior.
int *variable = scanf("%d",&n);
When you declare and initialize the pointer you assign the value to the pointer itself. The * is needed to show the compiler that you are declaring the pointer to the object of some type not the object itself
When you use the * later in the code you dereference that pointer.
void foo(void)
{
int a;
int *b = &a; //you assign the pointer `b` itself - no dereferencing
*b = 5; //you dereference the pointer and asssign the the referenced object
}
The "fresh" declared pointer (unless initialized with the reference to the valid object) does not point to the valid object and its dereferencing invokes the Undefined Behavior
void foo(void)
{
int a;
int *b = &a; //b is pointing to the valid object -> the variable `a`
int *c; //c is not pointing to valid object
int *d; //d is not pointing to valid object
c = malloc(sizeof(*c)); //now c is pointing to the valid object (if malloc has not failed of course)
*c = 5 // correct no UB
*d = 5; // incorrect - UB
*b = 5; //correct no UB
}
the syntax is similar (the * before the pointer name) but it does something completely different. I have noticed that it is a bit confusing for the beginners

In the following program the invocation of change_it() seems to have no effect. Please explain and correct the code? [duplicate]

This question already has answers here:
How to change a variable in a calling function from a called function? [duplicate]
(3 answers)
Closed 4 years ago.
void change_it(int[]);
int main()
{
int a[5],*p=1;
void change_it(int[]);
printf("p has the value %u \n",(int)p);
change_it(a);
p=a;
printf("p has the value %u \n",(int)p);
return 0;
}
void change_it(int[]) {
int i=777, *q=&i;
a = q; // a is assigned a different value
}
For starters, when you initialize p, you're giving a pointer the value of 1, when it needs a memory location. NULL uses 0, but that doesn't mean you can -or should- just assign integer values to pointers.
Just as an fyi, you can cast the value of 1 like this:
int a[5], *p = (int *) 1;
There's like -2 reasons for doing this, though, the -1th reason being that the minimal type safety that C provides should be respected, and the -2th being that it makes the code hard to understand for other people.
I'm going to assume what you meant to do was not declare a pointer with an address value of 1 though, and say you meant to declare a pointer that holds a value of 1. Unless you have another variable that holds the value of 1 already, you're going to have to first dynamically allocate the pointer, then set its value.
int* p = malloc(sizeof(int));
*p = 1;
If you had another variable to use, you could instead create the pointer on the stack rather than dynamically allocating it, like this:
int* q;
q = p;
Now, calling the same print function on both would yield this:
printf("p has the value %d\n", *p);
printf("q has the value %d\n", *q);
Output:
p has the value 1
q has the value 1
Addressing your main problem, you need to name the parameter in the change_it function, for example:
void change_it(int arr[])
Your program needs the parameter to be named, otherwise it has no idea of knowing you're trying to reference the array. The a variable you reference in the function is not bound to anything; the compiler will know be able to deduce what you're talking about.
Also, you don't need to redeclare the function prototype in your main function. The reason this is not a compiler error is that you can have as many declarations as you want, but only one definition. Again though, there's no reason to do this.
Another fyi, you don't have to name the parameters in your function prototypes, but it's good practice to both name them and be consistent with the names between the prototypes and the actual implementations so that people reading your code understand what's going on.
Also, you're using the %u specifier for the printf function, when you're not actually using unsigned decimal numbers. You're using signed decimals so you should use %d.
Lastly, your change_it function commits one crucial error preventing it from correctly changing the value of the passed-in array properly: you're setting the array that you passed in to the value of q.
Look at the function in your original code closely (pretend you named the input array a, as it looks like you mean to). You first declare an integer variable i and set its value to 777. Then, you create an integer-pointer variable q on the stack and correctly set its value to i. Note: You're not setting q to the value of i, but rather the address of i.
Why does this small but significant distinction matter? When you set a to q in the next line, you're changing the address of the array, specifically the first element of a five-element integer array, to point to the address of an integer variable. This is bad for a few reasons. First, the array is five integers long, but now it points to a single element. If and when you try to access elements 2-5, you'll get either meaningless garbage or a segmentation fault for trying to access memory you don't own. Even worse, the variable i is allocated on the stack, so when the function change_it exists, the function's data will be popped off the stack, and trying to access the address of i will yield either garbage or a segmentation fault for trying to access memory you don't own. See a pattern?
I'm not really sure how to correct this code, as I'm not sure what you were trying to accomplish, but correcting the aforementioned errors, your code now looks something like this:
#include <stdio.h>
void change_it(int arr[]);
int main()
{
int a[5];
int *p = a; // Equivalent to int *p = &a[0];
printf("a address: %p\n", a); // Should be equal to p
printf("p address: %p\n", p); // Should be equal to a
a[0] = 1;
printf("a[0] = %d\n", a[0]); // 1
printf("p has the value %d\n", *p); // 1
change_it(a);
p = a;
printf("a address: %p\n", a);
printf("p address: %p\n", p);
printf("a[0] = %d\n", a[0]);
printf("p has the value %d \n", *p);
return 0;
}
void change_it(int arr[])
{
int i=777;
arr[0] = i;
// Could be just:
// arr[0] = 777;
}
Output:
p address: 0x7fffc951e0b0
a[0] = 1
p has the value 1
a address: 0x7fffc951e0b0
p address: 0x7fffc951e0b0
a[0] = 777
p has the value 777
Note: Your memory address can and probably will be different from these, all it matters is that p and a are equal in both.
Anyways, hope this helps. Let me know if you have any questions.
Alright, you I believe do not have basic understanding of a function: First lets start with declaration and definition:
void change_it(int[]); // THIS IS DECLARATION
int main ()
{
void change_it(int[]); // THIS IS DECLARATION (duplicate and unnecessary
....
}
void change_it(int[] a) // THIS IS DEFINITION
{
int i=777, *q=&i;
a = q; // a is assigned a different value
}
declaration of the function only needs (you can put parameter name for readability) a parameter type, where as definition has to have name of the parameter because in definition parameters are local variables.
printf("p has the value %u \n",(int)p);
This will print the address of p not the value of p. So this should be
printf("p has the value %u \n", *p);
And finally we get to the body of a function. Where you are depending on somthing that have been locally assigned and putting it back into parameters
void change_it(int[] a)
{
int i=777, *q=&i;
a = q; // a is assigned a different value
}
so q is pointer and you are assigning address of local variable i to it. Well what happens when your program exists the function? i might disappear thus loosing its values and its address, which is assigned to q which means q is loosing its variable and value, and which is assigned to a which might loos its variable because it is pointing to i in your function.
This part here:
int a[5],*p=1;
void change_it(int[]); // Here, doesn't compile
printf("p has the value %u \n",(int)p);
That statement isn't just valid, as far as I know, you can't declare a function inside another function in C.
Also:
void change_it(int[]) // Here, an error
{
int i = 777, *q = &i;
a = q;
}
This function needs an argument, but you supplied only its type (being int[]),
void change_it(int a[]) fixes the problem
Your program does not compile and produce warnings. It would not work as you intended.
1) p is a pointer. To access value which it points to you have to dereference it using * dereference opearator.
2)
void change_it(int[]);
is not needed in the body of main.
3)
the invocation of change_it() seems to have no effect
If you want to change a[0] element inside the function change_it name the passing parameter to a and dereference the q pointer,
The working program may look as this:
#include <stdio.h>
void change_it(int a[]);
int main()
{
int a[5] = {0}; // init all element of `a` to `0`
int *p; // declare int pointer
p = a; // p point to array `a`
// print the first element of array `a`
printf("a[0] has the value %d \n",(int)*p);
// call function change_it, pass `a` as the argument
change_it(a);
printf("a[0] has the value %d \n",(int)*p);
return 0;
}
// change the value of the first element of array `a` to 777
void change_it(int a[]) {
int i=777, *q; // declare int i and pointer
q = &i; // pointer `q` points to the `i` now
a[0] = *q; // a[0] is assigned value = 777;
}
Output:
a[0] has the value 0
a[0] has the value 777

Following a pointer in C

I will show the entire code, but look for the quotes above the pointers as I will be talking about my problem there. I will tell you what I think happened there at the quote comments. The code compiles and runs, I just need help understanding parts of the code.
#include <stdio.h>
#include <stdlib.h>
int *get_data(int num_grades);
float calc_average(int num_grades, int grades[]);
void display_average(float ave);
int main()
{
int num_grades = 10;
const int MAX_GRADE = 100;
Below this quote box at: int *result = get_data(num_grades);
I have a pretty simple understanding of pointers at this point, as I've been introduced to them recently, however I can't seem to wrap my head around what happens when you assign a function to a pointer. What I think should happen is that the pointer int *result should be pointing at an address. Instead its pointing to a function that is also a pointer i think. So is this a pointer to a pointer at: int *result = get_data(num_grades); ?
I will put the rest of my question at the get_data function below.
int *result = get_data(num_grades);
^ Above ^
if (num_grades ==0)
printf("no grades to average\n");
else
{
float ave = calc_average(num_grades, result);
display_average(ave);
}
free(result);
return 0;
}
float calc_average(int num_grades, int grades[])
{
float ave;
int i;
int sum = 0;
for (i = 0; i < num_grades; i++)
{
sum+=grades[i];
}
ave = (float)sum/num_grades;
return ave;
}
void display_average(float ave)
{
printf("average: %.2f\n", ave);
}
Below this quote box,
I think this is a function pointer that returns a int pointer?
So, inside the body of the function, we create a new pointer, allocate memory for it, assign grades for each 'pointee' i think, and then I'm not sure why a[i] = grade is working, what are these indexes coming from, I don't understand why this is working if there is no array declared. Can someone explain what is happening here? How does this work? I'm really confused here.
int *get_data(int num_grades)
{
int* a;
a = malloc(num_grades * sizeof(int));
int i;
for (i = 0; i < num_grades; i++)
{
printf("enter a grade: ");
int grade;
scanf("%d", &grade);
if(grade<=100)
{
a[i] = grade;
}
else
{
printf("grade needs to be > 0 and <= 100\n");
i--;
}
}
return a;
^ Above, this whole function ^
}
get_data is a function which returns a pointer to an integer. First of all:
int *result = get_data(num_grades);
in this line you are not assigning to result a pointer to function, but the result of the function being called with num_grades as argument. That is to say, to the a you calculated in the body of get_data. And after that:
int *get_data(int num_grades)
this is the declaration of a function called get_data which takes one int parameter and returns a pointer to int. You could rearrange the spaces like this:
int* get_data(int num_grades)
if it makes things clearer. In this context, saying that get_data is a pointer to function would not even make sense, since it's immediately followed by its body. For reference:
int (*get_data)(int num_grades);
this is how the declaration of a pointer to function taking one int param and returning an int looks like. And there can't be a function body after it.
... however I can't seem to wrap my head around what happens when you assign a function to a pointer.
You aren't assigning a function to a pointer; you're assigning the return value of the function (which happens to be an int * value) to a variable which happens to store int * values.
So is this a pointer to a pointer at: int *result = get_data(num_grades); ?
No. int * means 'pointer to int'.
I think this is a function pointer that returns a int pointer?
No. The function returns an int * (pointer to int). There is a function pointer in your code, though that isn't a function (because it's a function pointer) and it doesn't return anything (because it's not a function; it's a function pointer).
Remember, int * means 'pointer to int'.
and then I'm not sure why a[i] = grade is working, what are these indexes coming from, I don't understand why this is working if there is no array declared. Can someone explain what is happening here? How does this work? I'm really confused here.
The array[index] operator is actually a pointer[index] operator. It's syntactic sugar for *(array + index) or *(pointer + index).
Whenever an expression that has an array type is used (with the exception being taking the sizeof or &addressof an array), the expression is converted to a pointer. The pointer points to the first item of the array...
So whilst your pointer declaration will have different semantics for the sizeof and &addressof operators, it'll have the same semantics for the 'array subscript' operator.
A similar concept applies to functions (hence the "function pointer" explanation above). Technically, in your expression int *result = get_data(num_grades); you're not applying the function(argument) operator; you're applying the function_pointer(argument) operator. The expression denoting the function is converted to a function pointer...

C: Why do pointer and &pointer have different values?

If I run the following on OS X:
int main (void)
{
int* n; // initialise(declare) pointer
*n = 20; // the value in address pointed to by n is 20
printf("n: %i, n&: %i\n", n, &n);
return 0;
}
I get:
n: 1592302512, n&: 1592302480
Why the differing values?
Why do pointer and &pointer have different values?
The expression &n yields the address of n itself, while n evaluates to the value of the pointer, i.e. the address of the thing it points to.
But note that you have undefined behaviour First of all, because you are de-referencing an uninitialized pointer. You need to make n point somewhere you can write to.
For example,
int* n;
int i = 42;
n = &i;
// now you can de-reference n
*n = 20;
Second, you have the wrong printf specifier for &n. You need %p:
printf("n: %i, &n: %p\n", n, &n);
int* n declares a variable called n which is a pointer to an integer.
&n returns the address of the variable n, which would be a pointer to a pointer-to-integer.
Let's say we have the following code:
int a = 20; // declare an integer a whose value 20
int* n = &a; // declare a pointer n whose value is the address of a
int** p = &n; // declare a pointer p whose value is the address of n
In this case we would have the following:
variable name | value | address in memory
a | 20 | 1592302512
n | 1592302512 | 1592302480
p | 1592302480 | who knows?
In your code
int* n; //initialization is not done
*n = 20;
invokes undefined behavior. You're trying to de-reference (write into) uninitialized memory. You have to allocate memory to n before de-referencing.
Apart form that part,
n is of type int *
&n will be of type int **
So, they are different and supposed to have different values.
That said, you should use %p format specifier with printf() to print the pointers.
Just as an alternative, let me spell this out a different way.
char *ptr;
char c='A';
ptr = &c;
In this code, here's what's happening and what values are found when we qualify ptr in different ways.
ptr itself contains the address in memory where the char c variable is located.
*ptr dereferences the pointer, returning the actual value of the variable c. In this case, a capital A.
&ptr will give you the address of the memory location that ptr represents. In other words, if you needed to know where the pointer itself was located rather than what the address is of the thing that it points to, this is how you get it.

Why is there an asterisk after a function type declaration in C?

My question is in the title and is more of a syntax related question. Does anyone know what the * is doing in the function below? See here:
int* reat(int *n)
{
int i, *array;
do
{
printf("n="); scanf("%d", n);
} while (*n < 1);
array = (int *)malloc(*n * sizeof(int));
for (i = 0; i < *n; i++)
{
printf("%d. broj: ", i + 1);
scanf("%d", array + i);
}
return array;
}
The syntax
int i, *array;
declares i to be a variable of type int and array to be a variable of type int*. This sort of declaration isn't particularly common, but is legal C code.
Hope this helps!
The * in int* reat(int *n) indicates in the return that this function is returning a pointer to an integer value rather than the integer value itself. The * indicates in the argument list that this function also wants a pointer to an integer value rather than a "raw" integer value for its argument.
For example,
int x = reat(n); // assume n is a pointer to an int
probably won't compile on most systems. If it does, you'll be storing a memory address in x rather than the integer value you were expecting. Instead write
int *x = reat(n)
to store in x the pointer (to some integer value) returned by reat(). Consider this function:
int addone(int x) {
return 1 + x;
}
This function takes an integer value for its argument. To access the value of the integer pointed to by the return from reat() and use it in addone(), we'll need to call it like so:
int *x = reat(n)
addone(*x)
Thereby dereferencing x with the * operator to access the integer value it points to. addone(x) won't compile because x, without dereferencing, is a memory address and not an integer.
Understanding when the * is being used to define a pointer and when its being used to dereference one will become second nature over time. Trust that any time it shows up in a function definition, whether as an argument or a return, it indicates a pointer is being used.

Resources