Given the following Code
int main()
{
int z;
int **x;
int * y;
x = (int**)malloc(sizeof(int*));
y = (int*)malloc(sizeof(int));
*y = 6;
*x = y; // Point 1
z = 3;
*x = &z; // Point 2
}
I am to draw box-and-circle diagrams of variables at point 1 and point 2.
Following is what i have got point 1.
Following is what i have got for point 2.
can anyone confirm if my approach is correct and my solution? sorry i am new to pointers and c.
Let's take this step by step. First, we reserve a few locations on the stack for the variables.
Next, allocate a small block the size of int pointer.
The newly allocated block should eventually be assigned an address of an int since X is a pointer to a pointer to an int. Next, allocate another small block.
Now put the address of y into the location pointed to by x
Lastly, assign 3 to z and change the value that x is pointing to, which will now be the address of z.
Hope this helps.
At point 1:
a. y contains the address of a dynamically allocated block of memory (let's call this "Block A") that contains the value 6
b. x contains the address of a different dynamically allocated block of memory (let's call this "Block B"), and "Block B" contains the address of "Block A".
c. z is an uninitialized int
At point 2:
a. y is unchanged from point 1
b. z now contains the value 3
c. x still contains the address "Block B", but "Block B" now contains the address of z rather than the address of "Block A".
Diagrammatically, where circles are variables with automatic storage duration (i.e. x, y and z) and rectangles are dynamically allocated blocks of memory:
NO!! This should clear your doubt. Consider the address(y)=300, address(z)=400. content(300)=6, content(400)=3
*x = y; // Point 1
The above statement says that the content of pointer x will be the address of y. So the pointer x is pointing to pointer y. (i.e. content(x)=300 )
*x = &z; // Point 2
The above statement says that the content of pointer x will be the address of z. So the pointer x is pointing to pointer z. (i.e. content(x)=400 )
NOTE: In order to access the values you have to do **x which will finally access the values.
We know that (*) is dereference operator.
Now lets try to access the values using above terminology.
Point 1: **x => *(*x) => *(address(y)) => *(300) => content(300) => 6.
Point 2: **x => *(*x) => *(address(z)) => *(400) => content(400) => 3.
I'm not wholly familiar with this, but x is of type pointer-to-pointer-to-int - two layers of indirection. Y is of type pointer-to-int - one layer. However, the diagram shows them both having the same indirection from the underlying storage. You do this for the second diagram where you take the address of z, but taking the address of z is the same level of indirection as assigning y to *x, as in both cases, you're telling x to point to a memory address that points directly to memory.
So in short, I think your "point 1" diagram should be similar to your "point 2" diagram, with x's "pointer box" pointing to y's "pointer box".
Edit: I'm also not sure about the "point 2" diagram in that it seems to imply that x is pointer-to-int, as its pointer points directly to z's memory - but it's been a long time since I've seen box-and-pointer diagrams (which this essentially seems to be) to know whether there's an alternative way to add that layer of indirection in. I actually think "Z" and "3" should be in the same box as in box-and-pointer diagrams, since z directly refers to the underlying storage.
Related
If I run the following code:
int main(){
int x = 0;
int* y = &x;
&x = y;
}
I get the error:
lvalue required as left operand of assignment
I understand this means that when using the addressof operator, the pointer produced is not a valid lvalue, as is reflected in the c documentation.
My question simply is: why?
What is the reason that I cannot change the value of the pointer to my variable x? Is it to prevent the programmer from making mistakes, or does it fundamentally make no sense (in which case please explain why.)
In this line:
&x = y;
Sounds like you're trying to say "I want x to be stored in the address y".
When your declare a variable (x), its address (what you call "pointer value") is a constant value. It's NOT an "lvalue". ("l" for "left", a left part of an assignement operation, so something assignable.)
Also you're not meant to decide yourself where the system sets the datas in memory.
Plus, you're not even sure the "y" address is an allocated place allowed to be written by your process.
Three reasons here to not let you do that. :)
Here & operator gives you the address of the variable x and you are trying to assign something to that address, but that's not possible, it doesn't make sense.
If you want to change the value stored in x, just assign to it:
x = 5;
If you have a pointer (int*) y and you want to assign its value to x, use * operator to get the value y points to (stored in that address) and assign it to x:
x = *y;
If you want to assign the pointer y to x, it is not possible. Use another poiner for for that.
int *y1 = y;
In your code
&x = y
This line shows an error as &x is a constant pointer and hence cannot be changed after it has been initialized
Im fairly new to C programming and I am confused as to how pointers work. How do you use ONLY pointers to copy values for example ... use only pointers to copy the value in x into y.
#include <stdio.h>
int main (void)
{
int x,y;
int *ptr1;
ptr1 = &x;
printf("Input a number: \n");
scanf("%d",&x);
y = ptr1;
printf("Y : %d \n",y);
return 0;
}
It is quite simple. & returns the address of a variable. So when you do:
ptr1 = &x;
ptr1 is pointing to x, or holding variable x's address.
Now lets say you want to copy the value from the variable ptr1 is pointing to. You need to use *. When you write
y = ptr1;
the value of ptr1 is in y, not the value ptr1 was pointing to. To put the value of the variable, ptr1 is pointing to, use *:
y = *ptr1;
This will put the value of the variable ptr1 was pointing to in y, or in simple terms, put the value of x in y. This is because ptr1 is pointing to x.
To solve simple issues like this next time, enable all warnings and errors of your compiler, during compilation.
If you're using gcc, use -Wall and -Wextra. -Wall will enable all warnings and -Wextra will turn all warnings into errors, confirming that you do not ignore the warnings.
What's a pointer??
A pointer is a special primitive-type in C. As well as the int type stored decimals, a pointer stored memory address.
How to create pointers
For all types and user-types (i.e. structures, unions) you must do:
Type * pointer_name;
int * pointer_to_int;
MyStruct * pointer_to_myStruct;
How to assing pointers
As I said, i pointer stored memory address, so the & operator returns the memory address of a variable.
int a = 26;
int *pointer1 = &a, *pointer2, *pointer3; // pointer1 points to a
pointer2 = &a; // pointer2 points to a
pointer3 = pointer2; // pointer3 points to the memory address that pointer2 too points, so pointer3 points to a :)
How to use a pointer value
If you want to access to the value of a pointer you must to use the * operator:
int y = *pointer1; // Ok, y = a. So y = 25 ;)
int y = pointer1; // Error, y can't store memory address.
Editing value of a variable points by a pointer
To change the value of a variable through a pointer, first, you must to access to the value and then change it.
*pointer1++; // Ok, a = 27;
*pointer1 = 12; // Ok, a = 12;
pointer1 = 12; // Noo, pointer1 points to the memory address 12. It's a problem and maybe it does crush your program.
pointer1++; // Only when you use pointer and arrays ;).
Long Winded Explanation of Pointers
When explaining what pointers are to people who already know how to program, I find that it's really easy to introduce them using array terminology.
Below all abstraction, your computer's memory is really just a big array, which we will call mem. mem[0] is the first byte in memory, mem[1] is the second, and so forth.
When your program is running, almost all variables are stored in memory somewhere. The way variables are seen in code is pretty simple. Your CPU knows a number which is an index in mem (which I'll call base) where your program's data is, and the actual code just refers to variables using base and an offset.
For a hypothetical bit of code, let's look at this:
byte foo(byte a, byte b){
byte c = a + b;
return c;
}
A naive but good example of what this actually ends up looking like after compiling is something along the lines of:
Move base to make room for three new bytes
Set mem[base+0] (variable a) to the value of a
Set mem[base+1] (variable b) to the value of b
Set mem[base+2] (variable c) to the sum mem[base+0] + mem[base+1]
Set the return value to mem[base+2]
Move base back to where it was before calling the function
The exact details of what happens is platform and convention specific, but will generally look like that without any optimizations.
As the example illustrates, the notion of a b and c being special entities kind of goes out the window. The compiler calculates what offset to give the variables when generating relevant code, but the end result just deals with base and hard-coded offsets.
What is a pointer?
A pointer is just a fancy way to refer to an index within the mem array. In fact, a pointer is really just a number. That's all it is; C just gives you some syntax to make it a little more obvious that it's supposed to be an index in the mem array rather than some arbitrary number.
What a does referencing and dereferencing mean?
When you reference a variable (like &var) the compiler retrieves the offset it calculated for the variable, and then emits some code that roughly means "Return the sum of base and the variable's offset"
Here's another bit of code:
void foo(byte a){
byte bar = a;
byte *ptr = &bar;
}
(Yes, it doesn't do anything, but it's for illustration of basic concepts)
This roughly translates to:
Move base to make room for two bytes and a pointer
Set mem[base+0] (variable a) to the value of a
Set mem[base+1] (variable bar) to the value of mem[base+0]
Set mem[base+2] (variable ptr) to the value of base+1 (since 1 was the offset used for bar)
Move base back to where it had been earlier
In this example you can see that when you reference a variable, the compiler just uses the memory index as the value, rather than the value found in mem at that index.
Now, when you dereference a pointer (like *ptr) the compiler uses the value stored in the pointer as the index in mem. Example:
void foo(byte* a){
byte value = *a;
}
Explanation:
Move base to make room for a pointer and a byte
Set mem[base+0] (variable a) to the value of a
Set mem[base+1] (variable value) to mem[mem[base+0]]
Move base back to where it started
In this example, the compiler uses the value in memory where the index of that value is specified by another value in memory. This can go as deep as you want, but usually only ever goes one or two levels deep.
A few notes
Since referenced variables are really just numbers, you can't reference a reference or assign a value to a reference, since base+offset is the value we get from the first reference, which is not stored in memory, and thus we cannot get the location where that is stored in memory. (&var = value; and &&var are illegal statements). However, you can dereference a reference, but that just puts you back where you started (*&var is legal).
On the flipside, since a dereferenced variable is a value in memory, you can reference a dereferenced value, dereference a dereferenced value, and assign data to a dereferenced variable. (*var = value;, &*var, and **var are all legal statements.)
Also, not all types are one byte large, but I simplified the examples to make it a bit more easy to grasp. In reality, a pointer would occupy several bytes in memory on most machines, but I kept it at one byte to avoid confusing the issue. The general principle is the same.
Summed up
Memory is just a big array I'm calling mem.
Each variable is stored in memory at a location I'm calling varlocation which is specified by the compiler for every variable.
When the computer refers to a variable normally, it ends up looking like mem[varlocation] in the end code.
When you reference the variable, you just get the numerical value of varlocation in the end code.
When you dereference the variable, you get the value of mem[mem[varlocation]] in the code.
tl;dr - To actually answer the question...
//Your variables x and y and ptr
int x, y;
int *ptr;
//Store the location of x (x_location) in the ptr variable
ptr = &x; //Roughly: mem[ptr_location] = x_location;
//Initialize your x value with scanf
//Notice scanf takes the location of (a.k.a. pointer to) x to know where
//to put the value in memory
scanf("%d", &x);
y = *ptr; //Roughly: mem[y_location] = mem[mem[ptr_location]]
//Since 'mem[ptr_location]' was set to the value 'x_location',
//then that line turns into 'mem[y_location] = mem[x_location]'
//which is the same thing as 'y = x;'
Overall, you just missed the star to dereference the variable, as others have already pointed out.
Simply change y = ptr1; to y = *ptr1;.
This is because ptr1 is a pointer to x, and to get the value of x, you have to dereference ptr1 by adding a leading *.
I'm very new to C. I come from a Java background, and I'm having a hard time understanding pointers. My understanding of what *x = 1 is take the memory address of x and assign it to 1, where as x = 1 means assign the variable x to the value 1.
Am I correct?
Well, as written you have it completely backwards, since you're saying assign x to the value 1 etc.
x=1 means store the value 1 to the variable x.
*x=1 means store the value 1 at the memory address x points to.
*x = 1;
means that x contains a memory address, assign 1 to that memory address.
x = 1;
means assign 1 to the variable x.
x = VARIABLE
*x = POINTER TO ADDRESS
By saying x=1 means you are directly assigning the value 1 into the x. Where as *x=1 has a bit different approach.
Say, int y = 10 and x is a pointer which is pointing to the address of y by defining int *x = &y. After declaration of *x, through out the program, *x will be treated as the value at the address of y. So, when *x=1 is used, the the value at the address of y, which was 10 earlier, will be changed to 1 now. Thus, y=1 and *x=1 are internally doing same thing.
You can follow this link for detailed understanding in simpler way about C pointers.
suppose I have the following code in C:
int x = 1025;
int *y = &x;
What is &y? Is it the address in memory of the pointer variable y?
What is the pointer variable y? Does it hold the address of the variable x?
What is &x? Is it the address in memory of the variable x itself or is it the address its value, 1025?
What is the variable x? Is it the address of its value, 1025?
What is *y? Is it the address of 1025 = variable x ?
and the big one...
If printing &y displays the address of y, printing &x displays the address of x, but printing x/*y just prints 1025, how would I print the address of 1025?
Sorry if some of these questions seem really obvious, but I've had a lot of confusion messing with pointers that I'm trying to clear up.
[EDIT] Guys, I found my mistake; I was thinking that the variable x would hold the address of the sequence of bytes representing 1025. Standard Java-to-C maladjustment. Thank you all for the responses
Given:
int x = 1025;
int *y = &x;
Q1. What is &y? Is it the address in memory of the pointer variable y?
Yes. It is the address of the variable y, and has the type int **.
Q2. What is the pointer variable y? Does it hold the address of the variable x?
Yes. It is a pointer variable that (after the code fragment) holds the address of x.
Q3. What is &x? Is it the address in memory of the variable x itself or is it the address its value, 1025?
It is the address of the variable x. It so happens that x holds 1025 at the moment, but when that value changes, &x still points to the variable x, and therefore to the current value of x and not to 1025 (because x contains a different value now).
Q4. What is the variable x? Is it the address of its value, 1025?
The variable x is a memory location that currently holds the value 1025, but this could change. Values such as 1025 do not themselves have addresses — that is a concept from OO languages (I think Smalltalk has that sort of concept; I think Java uses it for object types, but not the simple non-object types like int‡) and not a C concept.
Q5. What is *y? Is it the address of 1025 = variable x?
It is not the address of 1025; that's the easy part. If you use int i = *y;, then *y is the value in the variable that y points to, which is currently x, which currently has the value 1025, so i is set to 1025. If, however, you use *y = 1024;, then *y is the variable that y points to, which is x, so the value stored in x (and *y) changes from 1025 to 1024.
Q6. If printing &y displays the address of y, printing &x displays the address of x, but printing x/*y just prints 1025, how would I print the address of 1025?
The first two assertions are fine. The 'but' assertion needs to be written x / *y with a space between the / and the * as otherwise you have started a comment. However, that should not print 1025 but should print 1. If you are getting 1025, then you wrote something like:
printf("%d\n", x/*y); /* comment */);
There is no address for 1025 per se. There might be various addresses for various variables that currently hold the value 1025, but there is no single address for the value 1025. That is a non-C concept, as already mentioned.
‡ If someone disagrees with the Java or Smalltalk references, let me know by comment and I'll remove the one those that are wrong. They are not a key part of my argument — I'm just trying to explain that some languages do have a concept loosely analogous to 'address of 1025', even though C does not.
What is &y? Is it the address in memory of the pointer variable y?
Yep. You can have pointers-to-pointers as well.
int x = 357;
int *y = &x;
int **z = &y;
What is the pointer variable y? Does it hold the address of the variable x?
Yes. Basically, it is an integer-ish type that (as its value) holds the address of 'x'.
What is &x? Is it the address in memory of the variable x itself or is it the address its value, 1025?
The address to the variable, which, with an integer, is also where the value is stored.
What is the variable x? Is it the address of its value, 1025?
It is the location in memory of several bytes, that hold data. How the data is interpreted depends on the code that uses it. With integers, the data is meant to represent a number (like 1025) but it could just as easily be manipulated as if it was something else, like a couple chars or a float. Data in memory is merely data in memory - what gives it meaning is how it is used.
What is *y? Is it the address of 1025 = variable x ?
1025 is merely the data stored at the address of 'x', the value stored in those bytes of memory doesn't change the location of 'x' at all. Once 'x' is created, it's location in memory (for the duration of its lifetime) doesn't change.
So *y is x. *y 'dereferences' the address stored in 'y' (x's address), and so then you're operating on the block of memory that both 'x' and '*y' refer to.
If printing &y displays the address of y, printing &x displays the address of x, but printing x/*y just prints 1025, how would I print the address of 1025?
Printing x/*y should print 1. x = 1025. *y = 1025. 1025/1025 = 1
1025 doesn't have an address. 1025 is a bunch of bits in a few bytes somewhere. 1025 is the sequence of bits (that your code gives a meaning to, but that has no meaning on its own) stored in several bytes that is located at the address stored in 'x' and '*y'.
If we assume an integer is four bytes of memory (32 bit OS and hardware, let's say), then you have four bytes in some random location in RAM:
[01000100] [1101010] [00101001] [11010101] (gibbish binary for illustration)
The binary bits stored in those four bytes don't mean a thing, until your code decides how to interpret the meaning of those bits.
'x' is those four bytes. 1025 is converted to binary and stored in those four bytes. The address of 'x' is the address of those four bytes. 'y' is a chunk of bytes that you store the address of 'x' at. '*y' lets you operate on the bytes that 'y' stored the address of. Accessing *y gives the same bytes pointed to that x refers to.
What is &y? Is it the address in memory of the pointer variable y?
Yes.
What is the pointer variable y? Does it hold the address of the variable x?
Yes.
What is &x? Is it the address in memory of the variable x itself or is it the address its value,
1025?
It is the address of x. x can change, for example if you set it with 'x = 1024' in a later line, but its address would remain the same
What is the variable x? Is it the address of its value, 1025?
x is a variable, which means it takes up some space in memory, and the bits in that space have the integer value of 1025.
What is *y? Is it the address of 1025 = variable x ?
*y dereferences the pointer, which means it gets the value of the memory at that address. So it returns 1025.
Your 'big question' is just question #3.
What is &y? Is it the address in memory of the pointer variable y?
&y is the address at which the contents of variable y are stored, those contents being the address of (pointer to) an int.
What is the pointer variable y? Does it hold the address of the variable x?
Yes, y is a pointer that holds the address of variable x.
What is &x? Is it the address in memory of the variable x itself or is it the address its value, 1025?
&x is the address of x, so the address in memory of the variable itself, not of the constant value you initialized it with.
What is the variable x? Is it the address of its value, 1025?
The variable itself is just a region of storage in memory, an "object" in C terms. Internally, the compiler uses the name to find the address of that region of storage.
What is *y? Is it the address of 1025 = variable x ?
*y is the value of whatever y points to, in this case, 1025.
how would I print the address of 1025?
It is not legal to take the address of a literal constant in C (except string literals), for a variety of reasons, including that it might not have an address.
Yes, yes, the address (that's why & is called the "address of" operator), no, no.
Here's how you should think of variables in C. They are scraps of paper that you can write a value on. (The type of the value should match the type indicated on the piece of paper.) All the scraps of paper are bound together in a notebook so that you can address them by a page number, which we call the address.
Pointer variables are special pieces of paper on which you write the page number. You can later check the pointer, see which piece of paper it points to, and look at that instead.
It follows from this that:
A variable has an address. It's a piece of paper with a page number.
A value does not have an address. It's not a piece of paper, it's something like a number that you can write on a piece of paper. A number like 1025 does not have a page number, but when you write "1025" on a page you call x, then there is a page, with a page number, that has 1025 written on it.
To convince yourself that you can't take the address of a value, try something like &1025. The compiler won't allow that.
exactly. A pointer is a variable and as a variable has its own memory address.
Yes, the pointer y is initialized with the address of the variable x
&x is the address of the variable x. You can print it if you want to clearly see the difference.
The variable x is saved at a certain address in the memory. This is different from the value with which the variable is initialized, in this case 1025.
Again, to see the difference, try to print out the address of x and its value:
int x = 1025;
printf("%p", &x); //prints the address of x
printf("%d", x); //prints the value assigned to x
Last question: *y is the variable pointer and the dereference operator *, This means that you get the value saved in the variable that y points to.
Well actually if you print x/(*y) then you should get 1 as a result because you would have 1025/1025
I was wondering what the difference in is between calling a method like :
int x;
mymethod(x);
and
mymethod(&x);
Because C always does call-by-value, if you want the function to be able to change the x inside the function itself, you have to pass the address of x.
mymethod(x);
will pass x, for example if x is 2, you could as well have written mymethod(2)
mymethod(&x)
will pass the address to x. Now the method can change the value stored at that address, so after the function is completed, the actual value of x might have been changed.
Now you can also declare a pointer:
int* y; //y is now a pointer to a memory address
y = &x; //y now points to the memory address of x;
*y = 5; will set the "value found at the address y" to 5, thus will set x to 5;
mymethod(x) passes in the integer x as a parameter. mymethod(&x) passes in the address in memory of x. If you required a pointer-to-int as an argument, then you would use the second one.
In few words, when you declare a pointer, you precede it by an asterisk:
int *ptr;
When you pass &x instead of x, you are passing the memory address.
Please, read this useful introduction to the pointers.
Regards.
In the line:
int x;
you allocate a piece of memory in the size of "int".
for this explanation we will assume the size of int is 4 bytes (it might not be 4 bytes).
so after the line "int x;" there are 4 bytes in the memory assigned to "x".
the value of "x" is inside these 4 bytes:
for example, if x=4 then it will look in the memory like this:
[0, 0, 0, 4] or in binary [0000000, 00000000, 00000000, 00000010].
(In real life it could also be [4, 0, 0, 0], but I won't get into that).
so the VALUE of x is 4.
But lets say I want the address of "x", where it is placed in the memory.
This is where the operator "&" comes into play, using this operator I request the address of x.
so if [0, 0, 0, 4] starts at the location "0x12341234" in the memory, &x will return that (0x12341234).
Now, if I want to store the address in a variable, this variable's type is not "int", but it is something that points to the address of int which is being marked as "int*".
So:
int x = 4; // <-- allocates memory of 4 bytes and fills its value with the number 4.
int* pointer_to_x = &x; // <-- pointer_to_x points to the address where x is located in the memory.
if there is a method declared like so:
void mymethod(int x) than we pass THE VALUE of x, so the method is being called mymethod(x).
if there is a method declared like so:
void mymethod(int* x) than we pass a POINTER to the address of x, so the method is being called mymethod(&x).
It is really the tip of the iceberg, and I really tried to keep it simple as I could, so if you have further questions, just ask!
There are also terms called "by value" and "by reference" but you still need to understand better the difference between int and int* and than "by value" and "by reference" will be quite natural.