Difference between **ptr and &ptr - c

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 = &num;
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 .

Related

How to evaluate double pointers in c?

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).

passing a pointer address vs pointer to a pointer in C

I'm slightly confused between these two pieces of code:
version 1: (gives warnings after compiling)
int func(int *ptr2)
{
*ptr2 += 1;
}
int main()
{
int a = 5;
int *ptr = &a;
printf("Address of a: %x\n", a);
printf("Before: %x\n", ptr);
func(&ptr);
printf("After: %x\n", ptr);
return 0;
}
Output:
Address of a: 5770a18c
Before: 5770a18c
After: 5770a18d
version 2:
int func(int **ptr2)
{
*ptr2 += 1;
}
int main()
{
int a = 5;
int *ptr = &a;
printf("address of a: %x\n", &a);
printf("Before: %x\n", ptr);
func(&ptr);
printf("After: %x\n", ptr);
return 0;
}
Output:
Address of a: cc29385c
Before: cc29385c
After: cc293860
If I'm understanding pointers in C correctly when we pass by reference, we are creating a pointer to that location. This allows us to change the value at the address held by the pointer through the dereference operator.
However, if we want to change the value held by a pointer, we use a pointer to a pointer. We pass the address of the pointer and create a new pointer to hold said address. If we want to change the value, we use the dereference operator to access our pointer's (defined elsewhere) value.
Hopefully I'm on the right track, but I'm struggling to visualize what's happening with version 1 specifically. Mainly, I'd just like to understand the difference in make-up and output between these two programs. I assume version 1 is still a pointer to a pointer, but why are the incremented values different between both programs? If version 1 is successfully incrementing ptr's value (which I suspect is not), why is that I cannot find code with the same syntax? I think I'm missing something fairly trivial here... Any help is appreciated
Based on your output, you appear to be compiling for a 32-bit system where addresses and int are of that size.
When you increment the value at *ptr with that type being int, it will simply add 1.
When *ptr resolves to an int* then it will increment by sizeof(int) because the value at the current address in this case is 4 bytes long, so we have to increase the address by the number of bytes that an int consumes so that we're pointing at the next int. Note that doing this is only valid if you actually have allocated memory at the subsequent address.
Generally you pass a T** when the callee needs to modify the address to point to - such as say, the callee performs a malloc() to allocate space for the pointer.
&ptr is a pointer to a pointer, but what is passed to func() is a pointer to int converted from &ptr in implementation-defined manner. Then, *ptr2 += 1; is incrementing int and add 1 to what is pointed by ptr2 (the pointer ptr in main(), which eventually have the same reepresentation as `int in your system).
In version 2, the pointer to a pointer is correctly passed to func(). Therefore, pointer aritimetic is performed and the size of int is added to the address.
Note that you invoked undefined behavior by passing data having wrong type to printf(). The correct way to print pointers is like this:
printf("Before: %p\n", (void*)ptr);
As you see, cast the pointer to void* and use %p specifier.

When to use * in pointer assignment? [closed]

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").

Pointers in C(Value of a pointer)?

C Language:
If (p) is a pointer declared as follows:
int a=5, *p;
p = &a;
What does *p will print?
*p won't "print" anything; that's just an expression that de-references the pointer, and produces whatever int value it points at.
You can print it with:
printf("*p=%d\n", *p);
and it will print 5 in your program since p points at a, and the value of a is 5.
The %d is important, it tells printf() to expect an int value, and to format that into a string for printing.
You can also print the pointer itself:
printf("p is %p, a is at %p\n", p, (void *) &a);
this will print the same address twice. The %p format specifier is used for printing addresses.
p is a pointer pointing to an int, *p will be the value of the variable. In this case a. Just for simplicity, you can think of & as the address of, * as the content of pointer as this post The 5-minute Guide to C Pointers points out.
remember a and p are only names, they stands for a variable. Assume the address of a is 1024(which is hardly the real case). Their relation is illustrated as below. The value of a is 5 , When we use p = &a, we assign the address of a, which is 1024 to p. *p will retrieves the value of the address p pointer to, which is what you're looking for: 5.
pic http://cizixs.u.qiniudn.com/pointer
If you want to print the vale, #unwind gives the answer.
Here is a tutorial that might clarify c pointer for you.
p is a pointer to an int. That means it can point to an address, in which an int will be stored.
Writing
p = &a
you set the pointer to point in the address in which integer a is stored.
When you try to print *p, you will get the value that is stored in the address that pointer p points. So you will get 5.
Keep in mind that operator & returns the address of a variable. So &a will return the address of the variable a . Also, when you want to get the value of the variable that is stored in address, if you have a pointer who points ins this address, you use the dereference operator, *. Hence, *p returns the value that is stored in the address that p points to.
p = &a;
p is pointer to a. i.e p holds address of a. and
*p
will give value of a. as & is used to get the address of a variable, * is used for dereferencing a pointer i.e. to get the value of the variable to which the pointer points.

Strange (for me) behavior of pointers

I'm reading about pointers, but i'm confused about their nature. Here is what I mean.
int x = 4;
//Here I declare p as integer pointer
int *p;
// Here I assign memory address of x to pointer p
p = &x;
// The line below prints result 4 which is expected. If I miss asterisk before p I'll get memory address instead of data which that memory address holds.
printf("%d", *p)
Summarizing when asterisk is mising before pointer it "points" to memory address. If asterisk preceded pointer it "points" to actual data.
So far so good.
But why that segment of code works correctly ?
int someIntVariable = 10;
const int *p = &someIntVariable;
printf("%d", *p);
If I miss asterisk the compiler gives me an warning " warning: initialization makes integer from pointer without a cast"
I expected p (if the compiler allows me to use p without asterisk) to hold memory address of someIntVariable instead of it's "value";
What is happening here ?
In the declaration:
const int *p = &someIntVariable;
The asterisk is not the dereference operator. It simply states p is a pointer. That line has the same effect as
const int *p;
p = &someIntVariable;
Here you are declaring a pointer and assigning a value to the pointer in one step.
It is equivalent to the following code:
const int *p;
p = &someIntVariable;
Here the * is not used as a de-referencing operator. It is used in the context of pointer declaration.
The const int * is a datatype - i.e. pointer to a const int. p is the name of the variable. It is on the LHS.
When asterik is on the RHS it has a different meaning. It means dereference.
I belive you got the warning:initialization makes integer from pointer without a cast,
when you tried these way
int someIntVariable = 10;
const int p = &someIntVariable;
printf("%d", p);
What your trying to do is , Your assigning a address to a normal variable and your expecting it to work but that is not how the normal variables used thats why pointers came into act to do that job and your trying to replace a pointer with normal variable
I still did not find the real answer to it but Just check out these question that I asked I wonder what really the &a returns?

Resources