scope of the variable in c using pointers and functions - c

#include<stdio.h>
int i = 10;
void func(int *q){
q = &i;
}
int main(void){
int i = 20;
int *p = &i;
printf("%d\n",*p);
func(p);
printf("%d",*p);
return 0;
}
here value of p in 2nd printf statement should be 10... but when I execute it returns 20 how n why?

It would print 10 if you do this
*q = i
in the called function.
Change the content of that variable whose address is with you in the called function in the local variable q. Don't change the content of the local variable q.
You asked me why? Will explain...
This is what happened when you called the function and printed the value. Well this is not an exhaustive list but this points out the key things that will help in this context.
You got the address of the variable i in p.
Then you pass it to the called function.
Called function now has a local variable whose content is same as that of p.
Now you change the content of that local variable with the address of the global variable i.
Then function ends.
Rest in peace - local variable q. It is dead.
Then you again access *p in main() - meaning you looking for what value there is in the address contained in p.
you get 20.
Is there any other way to get 10?
Well there is
func(&p);
And then you do this
void func(int **q){
*q = &i;
}
Now you print *p you will get 10.
Know few things clearly, no matter what C is pass by value. Even here also q is a local variable. But now we have the address of p of main()
in q. So when you write *q=&i then you are basically going to the address of p from main() and then write there the address of global variable i. Then you come back. q is again lost. Then you print it - as you change to the original variable (p), the content there is 10.
Code-1
func(p);
then in func()
void func(int *q){
*q = i;
}
Code-2
func(&p);
then in func()
void func(int **q){
*q = &i;
}

Here
q = &i
You are setting the value of q, which is a local variable. Changing it does not change the value of the variable passed to func().
To have the 2nd call to printf() print 10, you want to write to where q is pointing.
*q = i;
q points to the inner i, which this way is set to 10.

here value of p in 2nd printf statement should be 10 (changed) ... but when I execute it returns 20 (same as original).
How and why?
q in void func(int *q) is a copy of p when func(p); is called.
void func(int *q){
q = &i;
}
int main(void){
...
func(p);
...
}
The change q = &i; inside void func(int *q) does not affect p in main().

Related

Why is the pointer giving me this value?

I was studying for a test with the following question with the given output :
#include <stdio.h>
int main()
{
int i = 10;
int *const p = &i;
foo(&p);
printf("%d\n", *p);
}
void foo(int **p)
{
int j = 11;
*p = &j;
printf("%d\n", **p);
}
Output : 11 11
I understand that the address of *p pointing to int i is passed to the function foo. Here, **p is a pointer pointing to *p, where *p points to int i.
In the function, **p pointer changes and points to int j, and the first printf is called and 11 is printed.
What I don't understand is the output from the 2nd printf function. Why is it printing 11, when it should be 10? I've checked and the value of int i and it did not change, so shouldn't dereferencing *p give 10 and not 11.
Can someone explain to me the logic behind what is happening and why is it happening?
First you asign p the address of i and you input the address of p to the function foo and inside the foo function the the value of p becomes what every the value in j (*p = &j). When the memory address changes in the foo function you are not changing it back.
NOTE: There the variable p is not passed by value, It is passed to the function by reference. So any change you do to the p variable inside the foo function will affect the p variable inside the main function because they have the same memory address
The line:
*p = &j;
makes the original variable
int *const p
point to the address of the local variable
int j
After foo is called, that local variable j has since been deallocated from the stack, but p is still pointing to that same stack location which still has that value of 11. So you are illegally accessing deallocated stack memory but it just happens to remain the value of 11. So it is printed a second time.

what is the output and why the pointer in function does not affect the code?

why the op is 20 ?? not 10 ? I think the op should be 10 but I don't know what happened? can you please explain it step by step
void fun(int *ptr)
{
int q=10;
ptr=&q;
}
int main()
{
int r=20;
int *p=&r;
fun(p);
printf("%d",*p);
return 0;
}
Values of function arguments are copies of what is passed from caller. Modifying in callee will not affect caller's local variables.
Non-static local variables will vanish on exiting its scope. Therefore, you must not dereference pointers to them after that.
To obtain 10, your code should be:
#include <stdio.h>
void fun(int **ptr) /* pass a pointer to modify caller's local variable */
{static int q=10; /* add static to prevent it from vanishing */
*ptr=&q; /* dereference the pointer */
}
int main()
{int r=20;
int *p=&r;
fun(&p); /* pass the pointer */
printf("%d",*p);
return 0;
}
This is p and r (addresses are for instance based)
---------------- ---------------- ----------------
| r 20 | | p 1234 | | q 10 |
---------------- ---------------- ----------------
^ ^ ^
|_ Address of r |_ Address of p |_ Address of q
= 1234 = 9876 = 12121
To fun(),
void fun(int *ptr) {
int q = 10;
ptr = &q;
}
you provide p as ptr (ie 1234), then set ptr to the address of q
fun: ptr = 12121
then fun ends, and ptr dies with it, the memory didn't change for r
To change something you have to pass the address of that thing. Even if it is a pointer.
Giving the address of p to fun
fun( &p );
and changing fun() to accept a pointer to pointer
void fun(int **ptr) { // <== pointer to pointer
int q = 10;
*ptr = &q; // <== change r indirectly
}
here, ptr has the address of the pointer p, ie 9876
*ptr = &q; // changes the value of `r`
It´s basically because of two reasons:
p in main() and ptr in fun() are two different pointers, and
You pass p by value, not by reference.
At the function call:
fun(p);
you just pass p by value; Means it passes the address of r (what is actually the value of p) to ptr.
With ptr = &q; in fun() you just assign the address of q to ptr, but not to p.
Therefore, the output of dereferencing p at:
printf("%d",*p);
is of course 20, as p still point to r -> the value of p didn´t changed.
If you instead pass p by reference and declare ptr as pointer to pointer (**), plus qualify q with static qualifier (because function-local automatic variables will be destroyed after the function is executed once):
void fun(int **ptr) // ptr is declared as pointer to pointer to int.
{
static int q = 10; // q is static -> It won´t get destroyed after returning from `fun()`.
*ptr = &q; // dereferencing ptr to assign the address of q to p.
}
int main()
{
int r = 20;
int *p = &r;
fun(&p); // Notice the `&` to gain the address of `p`, not `r`.
printf("%d",*p);
return 0;
}
The output would be 10 as we actually assigned the address of q to p.
As a side note: It is considered as bad programming style to refer to static-qualified function-local variables from a caller. I just showed this to you for the educational purpose and to show the difference to your provided code.
Try to assign an object pointed to in the caller, here f.e. r, by a passed pointer inside of the called function, here ptr, with the actual value of the object in the called function, here q.

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

Pointer value as an argument

The value in the printf hasn't changed after applying the void function f, which is confusing me. It's basic stuff revolving pointers. The exact question is: Why isn't the end value 2 instead of 1?
int a=1, b=2;
void f(int* p) {
p=&b;
}
int main() {
int *p=&a;
f(p);
printf("%d\n", *p);
}
The *p value in main remains 1, and that's what's confusing me.
You need to dereference p and remove the & address operator from b
This assigns the value of b to the address where p points to:
void f(int* p)
{
*p = b;
}
The reson why it printed 1 and not e.g. the address of b is that you assigned: p = &b which just assigns the address of b to the local pointer variable p. This means it does not point to a anymore here. But since this was just a local copy it didn't change the value of the p you passed in main().
This makes it a little more obvious:
void f(int* ptr)
{
// assign a value
*ptr = 1337;
}
int main()
{
int local_integer = 666;
// prints "666"
printf("%d\n", local_integer);
f(&local_integer);
// prints "1337"
printf("%d\n", local_integer);
}
In your code you define a pointer to int on the stack. Its value is the same as the pointer in the main() function which happens to point to the ąddress of the variable a. Then you change its value (so the pointer on the stack now points to b) then you just drop that pointer.
void f(int* p) {
p=&b;
}
That is why if you dereference the pointer in main it still points to the address of the int variable a.

Pointers inside function in C

#include<stdio.h>
int q = 10;
void fun(int *p){
*p = 15;
p = &q;
printf("%d ",*p);
}
int main(){
int r = 20;
int *p = &r;
fun(p);
printf("%d", *p);
return 0;
}
I was playing with pointers. Could not understand the output of this.
Output is coming as 10 15.
Once p is pointing to address of q, why on returning to main function it's value changes? Also why it changed to the value '15' which was assigned to it in the function before '10'.
Because p is fun() is not the same p in main(). p , in each function, is local. So changing one doesn't affect other.
In C, all function parameters are passed by value, including pointers.
*p = 15; will set r to 15 as *p is pointing to the memory occupied by r in main() prior to its reassignment to &q;
Your reassignment p = &q; does not change what p points to in the caller main(). To do that, you'd need to doubly indirect the pointer, i.e. change the function prototype to void fun(int **p){, call it using fun(&p);, and reassign using *p = &q;.
Two steps:
First call to fun(), assigning the address of global int q [holding value 10] to p inside the fucntion scope and printing it. The first output ==> 10;
Once the call returns from fun(), it will hold the previous address, [passed from main()] and hence, will print the value held by that address [which is 15, modified inside fun()].

Resources