I am learning c, and I am quite confused about this double pointer question.
int x = 44;
int *p = &x;
int **t = &p;
bool a = (*t = &x);
I need to tell whether a will be true or false, and the correct answer is true. My thoughts were that t points to the address of p, and p points to the address of x. I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p. Can anyone explain?
int x = 44;
Declares integer variable x, which stores value of 44.
int *p = &x;
Declares integer pointer variable called p, p now stores the address of x.
int **t = &p;
Declares pointer to pointer of type int called t, t stores the address of p. (Pointers have addresses too)
bool a = (*t = &x);
In C;
'*' = Extracts the value from an address (Dereference)
'&' = Gives address of variable (Reference)
Since t is a pointer to the value stored in p. *t will be the value stored in p, which is the address of x. (We figured this out in the second line)
On the other hand since the & is used on variable x. This will extract the address of x.
Therefore *t == &x, which sets the boolean value a to true.
I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p.
Well, that is both right and wrong. The "point to the address of" should read "designate" and it is right.
First of all, you declared 3 variables
int x = 42;
int *p = &x;
int **t = &p;
Now this could be read as x is an int, *p is an int and **t is an int. Then we initialize x to value 42, then p to address of x, and t to address of p.
Given
int *p = &x;
the two L-value expressions x and *p not only are both of type int, and have the same value; they designate the same object. Just like 10565305 and Amy Finck designate the same user. This is also called aliasing - *p aliases x, just like Amy Fink and User 10565305 are your aliases on Stack Overflow (and the name x is not the object itself, just like you're a person, not a name).
Likewise with int **t = &p, we now notice that just like above, *t and p designate the same object, p. And ps current value is that of expression &x. Hence *t == &x must be true.
As for *ts type, if **t is an int, then *t must be int * (the law of conservation of stars in pointers ;) which of course matches the type of p, and type of &x.
It will be true. Here is the explanation:
In bool a = (*t = &x); the variable t holds address of p. You are de-referencing t i.e *t will point to the content stored in location of p.
The content stored in address of p is address of x. Remember *p = &x. Comparing *t == &x will then be true.
In the question you have mentioned *t = &x, if that is the original code it is still true, as assignment in (*t = &x); returns a non-null pointer. When that non-null pointer is converted to a boolean, it becomes true.
The first line declares a variable 'x' of type 'int', and assigns the numeric literal value 44 to that variable.
int x = 44;
The next line (2) declares a variable 'p' of type 'pointer to int', and assigns the value of the expression '&x' (which is the address of x, a pointer to int),
int *p = &x;
The next line (3) declares a variable 't' of type 'pointer to, pointer to int' (a pointer that contains a pointer to an int type), and assigns the expression '&p' (which is the address of p, a pointer to int,
int **t = &p;
The variable t is a 'doubly-indirected pointer'.
Now comes the 'tricky part'.
The next line (4) declares a variable 'a' which is a bool(ean) variable (true/false), and assigns the value of the expression on the rhs (right hand side, '(*t = &x)'. The parenthesis are there to ensure the intended order of precedence is observed. So we evaluate the expression '*t = &x'.
bool a = (*t = &x);
Here is the 'tricky' part, the code provided has an assignment '=' operator! If this were comparison, then the '==' operator would appear. So this statement takes the address of x (pointer to int), and stores it into *t (the location pointed at by t, and that location is a pointer to int).
Were this comparison, the expression would compare the same values, and would be true. But this is assignment. And an assignment expression returns the value assigned, which is the address of x (pointer to x). On most systems, that pointer is a location in memory (and could only be zero(NULL) if the variable were stored at the zero address).
The expression is of type 'pointer to int', but is converted (cast) to type bool. Since C considers false=0 and true anything not equal to 0, the value is converted from (likely not NULL) pointer to int to bool (true).
Had the parenthesis been omitted, then the assignment would still occur (right to left order of evaluation for assignment operator), but then the cast would occur. But remove the parenthesis, compile it and see what your compiler says.
You said:
I need to tell whether a will be true or false, and the correct answer is true. My thoughts were that t points to the address of p, and p points to the address of x. I know if you put **t, it should point to the address of x, but I thought if you just put *t it should point to the address of p. Can anyone explain?
Here is my attempt an an explanation:
The bold part is where you are confused. **t == x == *p, and *t == &x == p.
**t references the value stored in at x's address, not the address itself.
*t =p references the address of x, and dereferencing either of them give you the value of x.
Does this explanation clear things up? I can expand or make a sample program if it helps.
sample scratch code would be to printf these values to gain clarity:
int x = 42; //&x = 0x1234DEAD (or some other address, just picked one for an example)
int * p = &x; // p = 0x1234DEAD and &p = 0x5678BEEF (agian an example address)
int **t = &p; // t = 0x5678BEEF
printf("%d and %d and %d\n",**t, *p, x); //should be 42;
printf("%p and %p\n",*t, p); //should be 0x1234DEAD;
printf("%p\n",t); //should be 0x5678BEEF;
My thoughts were that t points to the address of p
Yes.
and p points to the address of x
Yes.
I know if you put **t, it should point to the address of x
No, **t is x.
but I thought if you just put *t it should point to the address of p.
No, *t is p.
The dereference operator "gives you" the pointed-to thing. Hence, since, p is also &x (because that's what you set it to), *t == &x.
It's moot though because you didn't actually compare with ==, you assigned with =, so your expression evaluates to the result of that assignment, which is &x, which is a non-NULL pointer, so the whole thing is "true-like". (Only a null pointer converts to false).
Related
I am currently preparing for an exam, and refreshing my pointer knowledge.
I am looking at this small exercise:
Consider the follow fragments of C programs. For each program, fill in the empty underlined spots such that the final value of the variable x is 0.
int x;
int *p;
p = &_____;
*p = _____;
I assume that the first underline is p = &x. I am little confused about the second one though.
What is the difference between p = and *p = in this situation, given that we already have int *p?
int *p;
... declares p as a variable of type int * (a pointer to int). Given that this code overall can be valid only if it appears inside a function, that declaration does not assign a value to p. As a result, the expression *p is not (yet) meaningful immediately after that declaration, despite being syntactically correct.
The subsequent
p =
assigns a value to (pointer) p. Your idea of p = &x; seems plausible. But this is about the value of pointer p itself, not about the value of the object to which p points.
Once p actually points to an object courtesy of the assignment to it, the value of the object to which it points can be accessed via *p, and in particular, a value can be assigned to the pointed-to object via *p = <value here>;.
Perhaps the thing tripping you up is that in no case is the * part of the name of the pointer. In the declaration on line 2, it is part of the type (int *) declared for variable p. In the assignment on line 4, it is a unary operator applied to variable p.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
As I'm learning C I often see pointers.
I get that a pointer is holding the hexadecimal value of a distinct location in memory. So a pointer is nothing other than e.g.:0x7fff5fbff85c
Every pointer is also of a distinct type.
int var = 10;
int *ptr = &var;
Ptr here points to the location of var. To get the value of var I have to dereference the pointer with *ptr.
Like
printf("Var = %d", *ptr);
would print `Var = 10;
However If I do a non inline declaration of a pointer like:
int var = 10;
int *ptr;
ptr = &var;
I don't have to use the * in the third line when I'm actually assigning the memory adress to the pointer.
But when I got a function that takes a pointer:
int var = 10;
void assignPointer(int *ptr) {
*ptr = 10;
}
Oh, wait! As I'm writing this I recognized that there are two different assignments for pointers:
*ptr = 10;
and
ptr = &var;
What is the difference? Am I in the first case first dereferencing the pointer, assigning 10 to the location that its holding?
And in the second case I'am assigning the actual location to the pointer.
I'm a little bit confused when to use the * and when not to in terms of assignment.
And if I'm working with arrays, why do I need pointers at all?
int array[];
"array" here is already holding the hexadecimal memory location. Doesn't that make it a pointer? So If I wanted to assign something to array wouldn't I write:
*array = [10, 2];
First I'm dereferencing, then I'm assigning.
I'm lost :(
EDIT: Maybe it's a bit unclear.
I don't know when you have to use a * when you are working with pointers an when not.
Everything that is carrying a hexadecimal is a pointer right?
The variable name of an array is carrying it's hexadecimal memory location. So why isn't it a pointer?
EDIT2: Thank you people you helped me a lot!
I don't know when you have to use a * when you are working with pointers an when not. Everything that is carrying a hexadecimal is a pointer right? The variable name of an array is carrying it's hexadecimal memory location. So why isn't it a pointer?
Last thing first - the name of an array is not a pointer; it does not store an address anywhere. When you define an array, it will be laid out more or less like the following:
+---+
arr: | | arr[0] Increasing address
+---+ |
| | arr[1] |
+---+ |
... |
+---+ |
| | arr[n-1] V
+---+
There is no storage set aside for an object arr separate from the array elements arr[0] through arr[n-1]. C does not store any metadata such as length or starting address as part of the array object.
Instead, there is a rule that says if an array expression appears in your code and that expression is not the operand of the sizeof or unary & operators, it will be converted ("decay") to a pointer expression, and the value of the pointer expression will be the address of the first element of the array.
So given the declaration
T arr[N]; // for any type T
then the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
arr T [N] T * Address of first element
&arr T (*)[N] n/a Address of array (same value
as above
*arr T n/a Value of arr[0]
arr[i] T n/a Value of i'th element
&arr[i] T * n/a Address of i'th element
sizeof arr size_t Number of storage units (bytes)
taken up by arr
The expressions arr, &arr, and &arr[0] all yield the same value (the address of the first element of the array is the same as the address of the array), but their types aren't all the same; arr and &arr[0] have type T *, while &arr has type T (*)[N] (pointer to N-element array of T).
Everything that is carrying a hexadecimal is a pointer right?
Hexadecimal is just a particular representation of binary data; it's not a type in and of itself. And not everything that can be written or displayed in hex is a pointer. I can assign the value 0xDEADBEEF to any 32-bit integer type; that doesn't make it a pointer.
The exact representation of a pointer can vary between architectures; it can even vary between different pointer types on the same architecture. For a flat memory model (like any modern desktop architecture) it will be a simple integral value. For a segmented architecture (like the old 8086/DOS days) it could be a pair of values for page # and offset.
A pointer value may not be as wide as the type used to store it. For example, the old Motorola 68000 only had 24 address lines, so any pointer value would only be 24 bits wide. However, to make life easier, most compilers used 32-bit types to represent pointers, leaving the upper 8 bits unused (powers of 2 are convenient).
I don't know when you have to use a * when you are working with pointers an when not.
Pretty simple - when you want to refer to the pointed-to entity, use the *; when you want to refer to the pointer itself, leave it off.
Another way to look at it - the expression *ptr is equivalent to the expression var, so any time you want to refer to the contents of var you would use *ptr.
A more concrete example might help. Assume the following:
void bar( T *p )
{
*p = new_value(); // write new value to *p
}
void foo( void )
{
T var;
bar( &var ); // write a new value to var
}
In the example above, the following are true:
p == &var
*p == var
If I write something to *p, I'm actually updating var. If I write something to p, I'm setting it to point to something other than var.
This code above is actually the primary reason why pointers exist in the first place. In C, all function arguments are passed by value; that is, the formal parameter in the function definition is a separate object from the actual parameter in the function call. Any updates to the formal parameter are not reflected in the actual parameter. If we change the code as follows:
void bar( T p )
{
p = new_value(); // write new value to p
}
void foo( void )
{
T var;
bar( var ); // var is not updated
}
The value of p is changed, but since p is a different object in memory from var, the value in var remains unchanged. The only way for a function to update the actual parameter is through a pointer.
So, if you want to update the thing p points to, write to *p. If you want to set p to point to a different object, write to p:
int x = 0, y = 1;
int *p = &x; // p initially points to x
printf( "&x = %p, x = %d, p = %p, *p = %d\n", (void *) &x, x, (void *) p, *p );
*p = 3;
printf( "&x = %p, x = %d, p = %p, *p = %d\n", (void *) &x, x, (void *) p, *p );
p = y; // set p to point to y
printf( "&y = %p, y = %d, p = %p, *p = %d\n", (void *) &y, y, (void *) p, *p );
At this point you're probably asking, "why do I use the asterisk in int *p = &x and not in p = y?" In the first case, we're declaring p as a pointer and initializing it in the same operation, and the * is required by the declaration syntax. In that case, we're writing to p, not *p. It would be equivalent to writing
int *p;
p = &x;
Also note that in a declaration the * is bound to the variable name, not the type specifier; it's parsed as int (*p);.
C declarations are based on the types of expressions, not objects. If p is a pointer to an int, and we want to refer to the pointed-to value, we use the * operator to dereference it, like so:
x = *p;
The type of the expression *p is int, so the declaration is written as
int *p;
C syntax is weird like this. When you declare a variable, the * is only there to indicate the pointer type. It does not actually dereference anything. Thus,
int *foo = &bar;
is as if you wrote
int *foo;
foo = &bar;
Pointers are declared similar to regular variables.The asterisk character precede the name of the pointer during declaration to distinguish it as a pointer.At declaration you are not de-referencing,e.g.:
int a = 0;
int *p = &a // here the pointer of type int is declared and assigned the address of the variable a
After the declaration statement,to assign the pointer an address or value,you use it's name without the asterisk character,e.g:
int a;
int *p;
p = &a;
To assign the target of the pointer a value,you dereference it by preceding the pointer name with *:
int a = 0;
int *p;
p = &a;
*p = 1;
Dereferenced pointer is the memory it points to. Just don't confuse declaring the pointer and using it.
It may be a bit easier to understand if you write * in declaration near the type:
int* p;
In
int some_int = 10;
int* p = &some_int; // the same as int *p; p = &some_int;
*p = 20; // actually does some_int = 20;
You are pretty much correct.
Am I in the first case first dereferencing the pointer, assigning 10 to the location that its holding? And in the second case I'am assigning the actual location to the pointer.
Exactly. These are two logically different actions as you see.
"array" here is already holding the hexadecimal memory location. Doesn't that make it a pointer?
And you got the grasp of it as well here. For the sake of your understanding I would say that arrays are pointers. However in reality it is not that simple -- arrays only decay into pointers in most circumstances. If you are really into that matter, you can find a couple of great posts here.
But, since it is only a pointer, you can't "assign to array". How to handle an array in pointer context is usually explained in a pretty good way in any C book under the "Strings" section.
You are right about the difference between assignment and dereferencing.
What you need to understand is that your array variable is a pointer to the first element of your continuous memory zone
So you can access the first element by dereferencing the pointer :
*array = 10;
You can access the nth element by dereferencing a pointer to the nth element :
*(array + (n * sizeof(my_array_type)) ) = 10;
Where the address is the pointer to the first element plus the offset to the nth element (computed using the size of an element in this array times n).
You can also use the equivalent syntax the access the nth element :
array[n] = 10;
One of your examples isn't valid. *ptr = 10;. The reason is that 10 is a value but there is no memory assigned to it.
You can think of your examples as "assigning something to point at the address" or "the address of something is". So,
int *ptr is a pointer to the address of something. So ptr = &val; means ptr equals the address of val. Then you can say *ptr = 10; or val = 10; cause both *ptr and val are looking at the same memory location and, therefore, the same value. (Note I didn't say "pointing").
According to my knowledge
**ptr = the address of memory location of the pointer variable ptr
&ptr = the address of memory location where the value of ptr is stored.
Am I correct or **ptr == &ptr?
If they are equal whether I can pass &ptr as a pass by address for a function as a replacement to ptr? Knowledge me on this.
It might help if you understand that for any pointer (or array) p and index i the expression *(p + i) is equivalent to p[i].
Now if i is zero that means we have *(p + 0) which is equal to *p, and its equivalent expression p[0]. That means when you do dereference a pointer you get the value of where it points.
Double-dereferencing a pointer only works if the pointer is pointing to another pointer.
You understanding of the address-of operator & is correct though.
Lets work on an example:
int a = 10;
int *p = &a; // Makes p point to the variable a
int **pp = &p; // Makes pp point to the variable p
Now if we do *pp we get the pointer p, and if we to **pp we get the variable a and its value.
printf("Value of a is %d\n", a); // Will print "Value of a is 10\n"
printf("Value of *p is %d\n", *p); // Will print "Value of *p is 10\n"
printf("Value of **pp is %d\n", **pp); // Will print "Value of **pp is 10\n"
Also, using pointer to pointer might seem not very usable, but if you think about dynamically allocated arrays things change. For a dynamically allocated array you need to use a pointer, and if you want a matrix (i.e. an array of arrays) you need to use pointer to pointer, if you want to allocate both "dimensions" dynamically.
Furthermore, while C doesn't support passing arguments by reference, it can be emulated using pointers, and if you need to pass a pointer by reference you do it by passing a pointer to a pointer (using the address-of operator).
Lastly a small fun fact. I started this answer by telling you that *(p + i) and p[i] are equivalent. Because of the commutative property of addition, the expression *(p + i) is equivalent to *(i + p) which means that p[i] is equivalent to i[p]. Don't do it in real code though, it will only obfuscate the code and cause confusion for new readers of the code.
Pay attention to the context: There is a difference when declaring and when using the pointer. In general, & is taking the address and ** is dereferencing the pointer twice. Obviously, these are not the same.
But in variable decfinitions, ** declares a pointer to a pointer. The declared variable can the take the address of a pointer as value:
int d = 10;
int *p = &d;
int **pp = &p;
This still doesn't mean that **p and & are the same: Here, the ** is part of the variable's type: pointer to pointer to int.
The same applies to function argumets: The function
void f(int **p);
takes a pointer to pointer to int as argument and you can pass it the address of a pointer to int.
'*' operator is used to hold a memory address.
'&' operator returns the address at which the variable is held.
for example
int a = 10; (10 is located in memory at, for example, 0xddffff0
int *b = &a; (&a is the same thing as 0xddffff0, so b now points to that address)
So '&' operator returns the address while '*' operator point at the address.
Actually my knowledge on double pointer was wrong .
**ptr - Value of the variable pointed by another pointer or we can say it is a pointer to a pointer
let me clarify with an ex
#include<stdio.h>
int main()
{
int num = 100 , *p , **ptr2ptr ;//Address of num=2000 ,p=3000 ,ptr2ptr=4000
p = #
ptr2ptr = &p;
printf("Single pointer *p =%d\n",*p);
printf("Double pointer **ptr2ptr=%d \n", **ptr2ptr);
printf("Address stored in p variable =%d \n", p);
printf("Address of p variable=%d\n", &p);
printf("Address of ptr2ptr=%d", &ptr2ptr);
return(0);
}
Output
Single pointer *p = 100
Double pointer **ptr2ptr= 100
Address stored in p variable =2000
Address of p variable=3000
Address of ptr2ptr=4000
From the above example it is clear **ptr2ptr(100) not equal to &ptr2ptr(4000) .
So I have found answer for my question .
The syntax commonly used in C to initialize pointers is
int *p = &x;
where p is our pointer and x is a previously declared variable. I unfortunately don't understand this syntax: *p is not equal to &x, but is instead equal to x. So why isn't the correct syntax
int *p = x;?
Does the compiler simply make an exception to the normal rules of variable assignment when dealing with pointers?
read it this way
int* p = &x;
ie int* is a type - a pointer to an int;
C declaration syntax is admittedly confusing. It generally follows the rule that "declaration follows use", but that's not a hard and fast rule.
The type name int* means "pointer to int", but to define an object p of type "pointer to int", we don't simply write that type name followed by the name of the object:
int* p;
Instead, we write:
int *p;
which means that *p is of type int; it follows from that that p must be of type int*.
You've probably noticed that both declarations are the same except for the spacing -- and the compiler doesn't care about spacing. In fact, some programmers prefer to write int* p;, even though it doesn't strictly follow the grammar, because it's clearer in this case.
The distinction becomes important if you want to define multiple objects in a single declaration:
int *p, *q;
means that *p and *q are both of type int. And
int *x, y;
means that *x and y are of type int -- which means that x is an int* and y is an int. Programmers who prefer to place the * next to the int need to split this up into two lines (which is a good idea anyway).
So for an object declaration, the extra specifiers are associated with the name being defined, not with the type. But an initializer applies to the newly created object. So this:
int *p;
means that *p is of type int, but this:
int *p = &x;
means that p itself is initialized with the value &x.
I won't try to argue that this is how C's declaration syntax should have been defined. It has its own consistent logic to it, but it's caused a lot of confusion. But it is the way it is.
The * character has a different meaning depending on where you find it. I can think of three meaning off the top of my head:
1. In a declaration
int *x;
Here, we are writing a variable declaration. We are creating a variable named x with type int *.
2. As a dereference in an expression
int *x = malloc(sizeof(int));
int y = *x;
Here we are using the same token but note that it is now inside an expression! (The right hand side of the equal sign is an expression). Here it means dereference.
3. As multiplication
int *x = malloc(sizeof(int));
int y = *x * *x;
Here we are using the same character for multiplication!
So what gives?
The compiler is able to use the context around the * character to determine which of these three cases we are in. It's certainly arguable that we should have different characters to represent these three things, but that's not the language that we have.
Going back to your declaration.
int *p = &x;
Let's take the first half. The "int *p" tells the compiler that the variable 'p' has a location in memory as a value and it should be interpreted as an 'int'. The second half, '&x', means to get me the location in memory of the variable x. So you can save 'location in memory of variable x' into a variable that represents 'location in memory.'
A real world analogy would be if you have houses on a street, each with an address (one of the houses would be 'x' in your example), and you also have a postcard, 'p,' on which you can write the address of a house. You can't put the house, x, on the postcard. You can only put the address of the house, &x, on the postcard.
int *p = &x;
When prefixed with a * in a declaration, an identifier is defined to be a pointer to the given type. For example, p is a pointer to x; Read it like this:
declare a pointer to an int called p
to the pointer p, assign the following value: the address of x
If we want to use p to get the value of x, we do what is called dereferencing: *p
For example:
int x = 35;
int *p = &x;
printf("x = %d\n", *p); // Prints x = 35
printf("%p\n", p); // Prints the address of x (which is the same as the value of p)
printf("%p\n", &p); // Prints the address of the variable p
int x = 5; // Declaring an integer 'x' and initializing it with the value 5.
int *p1 = &x; // Declaring Pointer 'p1' & Initializing it with address of 'x'.
printf("x = %d\n", *p1); // De-referencing Pointer 'p1' to get value of 'x'.
int *p2 = NULL; // Declaraing a Pointer to an int. Initialize it to NULL.
p2 = &x; // Assigning address of 'x' to pointer 'p2'.
printf("x = %d\n", *p2); // De-referencing Pointer 'p2' to get value of 'x'.
I'm learning C and C#. I'm learning about pointers and don't know what it means to combine the indirection operator and the address operator. What does it mean to combine the two?
Here is an example:
int *p, *q;
p = *&q;
& can be thought of as an address of (<something>) operator. So &q is address of q. Now * can be thought of as an value at (<something>) operator. So *q is basically the value stored at the address contained in q, i.e, * treats the variable as always containing an address. Now *&q, by associativity is *(&q). Which means
value stored at (address of q) which is same as value stored at q
address of q will be having another address since q is a pointer. So it is the same as
p=q
It means what it must mean. :)
If you read it from left to right, the right hand side simply means "the value retreived by following the pointer whose value is the address of q".
It's the same as p = *(&q);, and thus it's the same as p = q;.
I didn't even notice, but your program is wrong to declare p and q to be pointers. That won't compile, it should be:
int p, q;
p = *&q;
Also, this might be a bit ill-defined since q is never assigned a value before being read, not 100% sure about that.
&q;
would give you the address of the variable q, that is it's a pointer to q we could write
int ** pointerToQ = &q;
if we then say
*pointerToQ
we are asking for whater ever pointerToQ points to, which is q itself. So
*&q
Just gets us back to q.
Your example would set pointer p to the value of pointer q. It does nothing to the values pointed by p and q. It just sets the variable p, to the value of variable q, which both happen to be pointers to integer values. Lets see some examples:
*p = *q; // the value at the address pointed by q, gets copied to the address, pointed by p
p = &q; // this is illegal, since the type of &q is int ** (pointer to a pointer to an integer), but the type of p is int *