How the mechanisms of variable's scope work (local, static and global)?
I don't understand this output:
void foo1(int *z)
{
z = (int *)malloc(sizeof(int));
*z = 3;
}
void foo2(int *t)
{
*t = 3;
}
void main()
{
int y = 1;
int x = 2;
foo1(&y);
foo2(&x);
printf("%d %d", y, x);
}
output: 1 3
void foo1(int *z)
{
z = (int *)malloc(sizeof(int));
*z = 3;
}
I am not sure why you are using malloc, but *z ends up pointing to the memory address of the memory you just assigned with the malloc. So overriding the original pointer means the change isn't reflected in the original main() method.
A bit more clear:
You have a pointer * z that is pointing to the y from main(). When you use malloc it returns a pointer, so when you assign that to z, it is now pointing to a different block of memory that has nothing to do with the y from main(). You then assign this new block of memory the value of 3. Hence the original y is unchanged.
Starting in main, int y = 1; creates a local object named y and initializes it to 1.
Then int x = 2; creates a local object named x and initializes it to 2.
Then foo1(&y); calls foo1 while passing it the address of y.
In foo1(int *z), the parameter z is effectively an object local to the function foo1. As foo1 starts, z contains the address of y.
Then z = (int *)malloc(sizeof(int)); allocates memory and assigns the address of that memory to z. This changes z, so z no longer contains the address of y.
Then *z = 3; puts 3 in the place where z points, which is now the allocated memory. So the contents of the allocated memory change. y does not change because z no longer points to y, since z = (int *)malloc(sizeof(int)); changed z.
Then foo1 returns and main calls foo2(&x);, which calls foo2 while passing it the address of x.
In foo2(int *t), the parameter t is effectively an object local to the function foo2. As foo2 starts, t contains the address of x.
Then *t = 3; puts 3 in the place where t points. Since t points to x, this changes the contents of x, so now x contains 3.
Then foo2 returns.
Back inside main, printf("%d %d", y, x); prints the contents of y and x. Since y did not change, it is still 1. Since x did change, it is now 3.
Related
int main() {
int *x;
int *y;
y = x;
printf("%p %p", &x,&y); // prints 0061FF1C 0061FF18
printf("%p %p", x, y); // prints 00400080 00400080
return 0;
}
Why don't these print the same thing? I thought using just the x and the &x would get to the same value. Also, why are the bottom ones matching if the top one's arent?
When you say y = x in this case it just means that y assumes whatever pointer value x happened to have. You never initialized x with a value, so it's just some random junk.
The address of x and y themselves is going to be different. These are two separate variables representing two separate pointers. You can assign their value to be the same, but their address remains distinct.
You're probably confusing this behaviour with:
int x = 5;
int* y = &x;
Where now y == &x but &x and &y continue to remain distinct.
As C does not have references, you really don't have situations where two independent variables are ever the same address.
Suppose you wrote this:
int main() {
int x = 5;
int y;
y = x;
printf("%p %p", &x, &y);
printf("%d %d", x, y);
}
Would you expect both lines to print the same?
With int *x; you set x as a pointer. Its value is the address of the pointed value.
So:
*x = the integer value
x = the pointer, i.e., the address of the value, address stored at x
&x = the address of the pointer. This is the address of the address.
Then y=x; copies the uninitialized address, not the value.
Unable to figure out the dependency between the address of the specific variables, as appeared to the C complier, and the actual underlying hardware.
Consider example 1, after compiling of this code with cc t2.c, and executing it, it looks, it is not working as expected, the addresses of px and py are not getting interchanged for whatever reason.
Example 1:
#include <stdio.h>
void swap(int *,int *);
int main(){
int x=3;
int y=2;
int *px;
int *py;
px=&x;
py=&y;
printf("px = %x\npy = %x\n",&px,&py);
swap(px,py);
printf("After the swap\npx = %x\npy = %x\n",&px,&py);
}
void swap(int *px,int *py){
int temp;
temp=*px;
*px=*py;
*py=temp;
}
gdb of example 1:
6 int x=3;
(gdb) n
7 int y=2;
(gdb) n
10 px=&x;
(gdb) p x
$1 = 3
(gdb) p &x
$2 = (int *) 0x7efff5cc
(gdb) p px
$3 = (int *) 0x0
(gdb) p &px
$4 = (int **) 0x7efff5d4
(gdb) n
11 py=&y;
(gdb) p px
$5 = (int *) 0x7efff5cc
(gdb) p &px
$6 = (int **) 0x7efff5d4
....
pi#readonly:~/new$ cc t2.c
pi#readonly:~/new$ a.out
px = 7ea765fc
py = 7ea765f8
After the swap
px = 7ea765fc
py = 7ea765f8
Example 2:
int x = 1, y = 2 ;int *ip; /* ip is a pointer to an int */
ip = &x; /* ip now points to x */
y = *ip; /* y is now 1 */
*ip = 10; /* x is now 10 */
*ip = *ip + 1; /* x is now 11 */
*ip += 1; /* x is now 12 */
++*ip; /* x is now 13 */
(*ip)++; /* x is now 14, parentheses are required */
Ex 1 Q:
1) Am I understand correctly, that, starting from the $5, px - is exactly the same variable as x, except it has its value set to 0x7efff5cc in hexadecimal, which is simply the address of the variable x in the memory??
2) If we use int *ip declaration, does it mean, that variable ip has the value equals to the address of int? Then, what is the address of int, in hexadecimal?
3) What does mean the address of the variable, what is this 0x7efff5cc? In other words:
I know, there are RAM, L2, L3, L1 caches of CPU, ROM. So, Address of which specific memory this number is representing?
How many such 0x7efff5cc can hold those specific type of memory? Or, where I can check it on Linux system?
4) What does (int **) notation mean?
5) What's wrong with the program, how to fix it, in order to get the addresses of px and py interchanged after being passed as an argument values to the function swap?
Ex 2 Q:
5) Regarding the notation, am I understand it correctly, that as soon as we declare that the variable ip is a pointer to int, via int *ip, we cannot assign, for example, the decimal value to ip, later on, using assignment like: ip = 10; since, after the variable has been declared as pointer, it is used solely for holding the addresses of other variables, to which ip "is pointing to", in hexadecimal?
Ex 1 Q:
1) Am I understand correctly, that, starting from the $5, px - is
exactly the same variable as x, except it has its value set to
0x7efff5cc in hexadecimal, which is simply the address of the variable
x in the memory??
px is a pointer variable. That means px is a variable that contains an address. You assigned it to the address of x with px=&x, but you can assign any value to it.
2) If we use int *ip declaration, does it mean, that variable ip has
the value equals to the address of int? Then, what is the address of
int, in hexadecimal?
int *p is a pointer variable that points to an int. https://cdecl.org/?q=int+*ip%3B
3) What does mean the address of the variable, what is this
0x7efff5cc? In other words:
I know, there are RAM, L2, L3, L1 caches of CPU, ROM. So, Address of
which specific memory this number is representing?
0x7efff5cc is a virtual address that the OS has given to the data space in your program to store the int x;
How many such 0x7efff5cc can hold those specific type of memory?
Linux can have many programs running at the same time that have the same virtual address but map to different physical addresses.
Or, where I can check it on Linux system?
see this for information on how to see what the physical address is for a virtual address on linux: Is there any API for determining the physical address from virtual address in Linux?
4) What does (int **) notation mean?
the variable is a pointer to a pointer to an int.
5) What's wrong with the program, how to fix it, in order to get the
addresses of px and py interchanged after being passed as an argument
values to the function swap?
fixed issues in your swap program:
#include <stdio.h>
void swap( int **, int ** );
int main()
{
int x = 3;
int y = 2;
int *px;
int *py;
px = &x;
py = &y;
printf( "px = %x\npy = %x\n", px, py );
swap( &px, &py );
printf( "After the swap\npx = %x\npy = %x\n", px, py );
}
void swap( int **px, int **py )
{
int *temp;
temp = *px;
*px = *py;
*py = temp;
}
Ex 2 Q:
5) Regarding the notation, am I understand it correctly, that as soon
as we declare that the variable ip is a pointer to int, via int *ip,
we cannot assign, for example, the decimal value to ip, later on,
using assignment like: ip = 10; since, after the variable has been
declared as pointer, it is used solely for holding the addresses of
other variables, to which ip "is pointing to", in hexadecimal?
no you can change what ip points to.
int *ip;
ip = &x;
ip = &y;
ip++;
Your swap function is exchanging the values of x and y, not the values of px and py.
Since px == &x, that means *px == x, same is true for py.
For a function to write a new value to a parameter, you must pass a pointer to the parameter:
void foo( T *ptr )
{
*ptr = new_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
T var; // for any non-array type T
foo( &var ); // write a new value to var
...
}
This is true for any non-array type T, including pointer types. Let’s replace T with the pointer type P *, so the code is now
void foo( P **ptr )
{
*ptr = new_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new value to var
...
}
The semantics are exactly the same, all that’s changed is the type. If we want to write to a non-array object, we pass a pointer to that object. If we want to write to a pointer object, we pass a pointer to that pointer object.
So if you want you function to swap the values of px and py, it must be written as
void swap( int **ppx, int **ppy )
{
int *tmp = *ppx; // int * = int *
*ppx = *ppy; // int * = int *
*ppy = tmp; // int * = int *
}
and called as
px = &x;
py = &y;
swap( &px, &py );
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In the code below in order to swap between px and py you need a pointer to point to the address of py and px to swap them effectively.
My question is with the int temp when the value of px is put into it how does it give the correct value back because there is no pointer pointing to it to be able to give the right value and how is the address of int temp not clone to give a wrong value?
void swap(int px, int py)
{
int temp;
temp = px;
px = py;
py = temp;
}
//pointer version
void swap(int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Both functions swap the int values. But does that swap affect the calling code's ints?
With the second swap(), the effect of the swap is seen in the original a,b as that function works with the addresses of the original a,b.
int a = 1;
int b = 2;
swap_version2(&a, &b);
printf("%d %d\n", a, b); // prints 2 1
With the first swap(), the effect of the swapped is not seen in the original c,d. as the swap() function was swapping copies of c,d. Net effect: the first swap function simply wastes time. It does not swap c,d.
int c = 3;
int d = 4;
swap_version1(c, d);
printf("%d %d\n", c, d); // prints 3 4
There are two important things you need to know.
1) When calling a function in C, the arguments are always passed by value. If you make changes inside the functions to the variables holding the passed value, the changes will be lost the moment the function returns. In other words - any change made inside the function can't be seen outside the function.
2) When working with pointer the * operator in front of the pointer means the location pointed to by the pointer. It is called dereferencing the pointer. So if you do *px = 5; you do not change any pointer value! You change the value at the location pointed to by the pointer.
A closer look at your code:
In your first example you have something like:
void swap(int px, int py)
{
int temp;
temp = px;
px = py;
py = temp;
}
int main(void)
{
int x = 10;
int y = 100;
swap(x, y);
printf("%d %d\n", x, y);
return 0;
}
In C everything is passed by value. So when you call swap it is the values 10 and 100 which is passed to the function. It is not the variables x and y. In other words - px and py in the function has nothing to do with the variable x and y in main. This means that any change made to the variables px and py is lost when the function returns and x and y does not change.
Your second example is like this:
void swap(int px, int py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
int main(void)
{
int x = 10;
int y = 100;
swap(&x, &y); // Notice the & operator
printf("%d %d\n", x, y);
return 0;
}
As always we have pass by value. But in this case the values that you pass is the values of two pointer to int. More specific you pass the address of x and y.
Like before you can't change the value that is passed to the function (just like the first example) but you can change the value of whatever the pointer is pointing to.
Here you need to know that * in front of the pointer access whatever the pointer is pointing to.
So doing temp = *px will read the value pointed to by px. In this case it is 10 so temp gets the value 10.
Doing *px = *py reads the value py points to (i.e. 100) and place it where px points (i.e. x in main is now 100).
Doing *py = temp reads the value temp holds (i.e. 10) and place it where py points (i.e. y in main is now 10).
So when the function returns, the value of x and y has been swapped.
Notice that the code never uses a pointer to (aka the address of) temp. The variable temp is just used as an ordinary int.
In this function
void swap(int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
there are swapped values pointed to by px and py. The function does not swap the pointers themselves.
To swap the values pointed to by the pointers you need an intermediate memory where temporary to store the value pointed to by px that will be overwritten by the value pointed to by py.
Thus the function uses local variable temp that temporary stores the value *px.
Pay attention to that in this assignment statement
temp = *px;
the variable temp stores the value pointed to by px that is *px that has type int. It is not the pointer px itself that is assigned to temp.
when I try to swap these two integers using pointers, I get segmentation fault.
Basically before I swap, x is assigned to 1 and y is assigned to 2. After I swap x is assigned to 2 and y is assigned to 1.
The program takes two integers x and y and is supposedly meant to swap them:
int swap(int x, int y){
int *swapXtoY;
int *swapYtoX;
*swapXtoY = y;
*swapYtoX = x;
}
Function swap is expecting both of its argument as int, but you are passing int *. Compiler should raise a warning about this.
It seems that you have no idea how pointers work in C. Your function is just assigning two ints to local variables. Function should be like:
int swap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
swap method should accept two pointer, instead of two integers.
Try following.
int swap(int* x, int* y){
int temp = *x;
*x = *y;
*y = temp;
}
You must pass variables by address to functions to change their value.That being said,your functions should expect pointers as well.Here is a generic function that can swap variables of any C data type:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Swap(void *x,void *y,size_t bytes);
int main(void)
{
int x = 3, y = 4;
Swap(&x,&y,sizeof(int));
printf("x now : %d\n",x);
printf("y now : %d\n",y);
return 0;
}
void Swap(void *x,void *y,size_t bytes)
{
void *tmp = malloc(bytes);
memcpy(tmp,x,bytes);
memcpy(x,y,bytes);
memcpy(y,tmp,bytes);
free(tmp);
}
Firstly, your function passes its arguments by value1, which makes it impossible for the function to make any lasting changes to them.
Secondly, the swap idiom consists of:
defining an intermediate variable, temp, which is initializes to one of the two variables, for example x.
assigning the value of the second variable,y to the first (saved in temp) variable x (now temp has value x and x has value y).
finally, assigning temp, to the second variable, y (now x has the value of y and vice versa).
In C code, this would look like:
void swap (int *x, int *y ) {
// dereference x to get its value and assign it to temp
int temp = *x;
// dereference x and assign to it the value of y
*x = *y;
// complete the swap
*y = temp;
}
Then to call the function:
// if the variables are not pointers
swap(&x, &y);
// if variables are passed via pointers
swap(x_ptr, y_ptr);
You might want to check the meaning of the dereference operator * or address-of operator &.
1. By value: it passes a copy of the passed variable, which prevents any change outside the function.
Program:
int x;
int *y;
int **z;
z = (int **) malloc (sizeof(int *));
y = (int *) malloc (sizeof(int));
x = 1;
*z = &x;
*y = x;
.
.
.
Question:
What is the difference between:
*z = &x;
*y = x;
From what I understand *z points to the address of x and *y points to x, but for *y to point to x doesn't that require the address of x? I don't really understand what's going on with these two variables.
Edit:
I also want to know when do we know when a variable is allocated on the stack or on the heap?
Why is x,y, and z allocated on the stack?
Why is *y, **y, *z, **z, allocated on the heap?
Finally, does changing *z, change **z?
z is a pointer to a pointer (which will typically point to a dynamically allocated array of pointers).
y is a pointer to int. Again, more often than not it'll point to a dynamically allocated array of ints.
So, the *z = &x; is setting the pointer that z refers to to point at x. I.e., z points at a pointer, which (in turn) points to x.
*y = x; is taking the value of x and assigning it to the int pointed to by y.
For things like this, a picture is often helpful. So, our basic definitions give us this:
The we do:
z = (int **) malloc (sizeof(int *));
y = (int *) malloc (sizeof(int));
Which gives us this:
Then we do:
*z = &x;
*y = x;
Which gives us this:
In all of these, a dashed line signifies a pointer from one place to another, while the solid line indicates copying a value from one place to another.
We can then consider the long-term differences between them. For example, consider what happens if we add x=2; after all the assignments above.
In this case, *y will still equal 1, because we copied the value 1 from x to *y. **z will equal 2 though, because it's just a pointer to x -- any change in x will be reflected in **z.
This line stores the address of variable x in the memory pointed to by z:
*z = &x;
This line stores the value of x into memory pointed to by y:
*y = x;
The two assignment statements are unrelated: the second one makes a copy, while the first one does not. If you change the value of x and then retrieve **z, you will see the new value of x; however, retrieving *y would give you back the old value of x (i.e. 1).