Difference between `*&p` vs `&*p`? - c

int a=10;
int *p=&a;
now looking at &*p we first look at *p which is 10 and then at &10
which is the address of 10 or the address of a
In the case of *&p we first look at the address of p and then at the value in this address which is 10
But I understand that both *&p vs &*p are the same, why?

Lets draw your variables:
+---+ +---+
| p | --> | a |
+---+ +---+
That is, p is pointing to a.
Now if you do &*p then you first dereference p to get a, then you get the address of a, which leaves you with a pointer to a.
If we take *&p then you get the address of p to get a pointer to p, then you dereference that pointer to get p. Which is a pointer to a.
So while the expressions do different things, the end result is the same: A pointer to a.
And a descent compiler would probably just do nothing at all, since the dereference operator * and address-of operator & together will always cancel each other out, no matter in which order they are.

Considering below example
int a=10;
int *p=&a;
this
*&p
means here both * and & gets nullified and it result in p which is nothing but &a.
And this
&*p
means first dereference p which gives a and then reference & i.e address of a which is nothing but p, same as the first case.

By the clockwise / spiral rule:
For *&p:
+-----+
| +-+ |
| ^ | |
* & p ; |
^ ^ | |
| +---+ |
+-------+
We first take the address of p, which is at this point the address of the address of a.
Then we dereference that, which gives the address of a.
For &*p:
+-----+
| +-+ |
| ^ | |
& * p ; |
^ ^ | |
| +---+ |
+-------+
We first dereference p, which gives us a.
We then take the address of that, which gives us the address of a, just like before.

In this context, & takes the address (i.e., informally "adds *" to the type of the expression). Meanwhile * dereferences a pointer (i.e., "removes a *" from the type of the expression). Therefore:
int *p = …;
p; // int *
*p; // int
&*p; // int *
&p; // int **
*&p; // int *
So, yes, in this context the result is the same: a pointer to int, because the & and the * cancel out. However, this is also why the combinations are pointless: the result is the same as p by itself.

*&p == *(&p). &p is an pointer to the pointer or int. *(&p) is a value to which pointer of pointer points, which is value of p. To continue, **&p will print '10'.
&*p == &(*p) where *p is the value at which the pointer points (value of a). Now & is an address of a, which is p again. And to go further, *&*p will print value of a (10).

Related

can anybody help me to solve this pointer question in c

can anybody help me understand this code (in c)..
#include <stdio.h>
void main()
{
const int a =5;int b;
int *p;
p= (int *) &a;
b=a;
*p= *p +1;
printf(" value of p is = %d\n", *p);
printf(" value of b is = %d\n", b);
printf(" value of a is = %d\n",a);
}
result is
: value of p is = 6
: value of b is = 5
: value of a is = 6
With the instruction p = (int *)&a; you made p to point at a.
As a result expression *p refers to the variable a, hence *p = *p + 1; worked as equivalent to a = a + 1; – variable a got assigned its previous value (which was 5) incremented by 1.
So it's finally 6.
This, however, is an Undefined Behavior, as #interjay points out in this comment – the a variable is declared as const, which means it must not be modified. As a result the compiler might choose to allocate it in a read-only area of memory. It did not in your case, and an assignment succeeded, but in other case the modfication of the variable might silently fail (with a value remaining 5) or yield a memory access exception (and terminate the program) or whatever.
The intent of this code is to update the value of a through the pointer p. Let's strip away some things and start with the basics:
int a = 5;
int *p = &a;
We have an object named a that stores the integer value 5. We have another object named p that stores the address of a. After the two declarations above, the following conditions are true:
p == &a == some address value
*p == a == 5
The expression *p is equivalent to the expression a - assigning a new value to *p is the same as assigning a new value to a, so
*p = *p + 1
is the same as writing
a = a + 1
However, in the code you posted a has been declared as a const int. That means you are telling the compiler that the value of a is not supposed to change over its lifetime. The compiler will flag any statement like
a = a + 1
or
a++;
as an error. The compiler may also store a in read-only memory; if you never take the address of a (that is, if it's never the operand of unary &), the compiler may not reserve any storage for it at all and just replace any instance of it with the value (IOW, anywhere you would expect to see a reference to a in the machine code you would just see a literal 5), meaning there's nothing to write to at all.
But this code cheats - it declares p as a pointer to a non-const int. The type of the expression &a is const int * (pointer to const int), but the type of p is just int * (pointer to int). In the assignment
p = (int *) &a;
you are casting away the const qualifier on a. So when you write a new value to *p, the compiler doesn't know that you're trying to modify something that was declared as const so it won't flag it as an error.
The C language definition says that trying to update a const-qualified object through a non-const-qualified lvalue1 results in undefined behavior - the compiler is not required to handle the situation in any particular way. The result can be any one of:
a runtime error;
the value of a remaining unchanged;
behaving exactly as expected;
or something else entirely.
An lvalue is any expression that designates an object such that the object my be read or modified. Both a and *p are lvalues that refer to an integer object containing the value 5
Before the explanation, let me tell you that this is part is a bit problematic, and can lead to undefined behavior:
const int a =5;
p= (int *) &a;
You should remove const, because in this case you want to modify the contents of a through pointers. Some compilers (such as clang, as someone mentioned in the comments) might perform optimizations, like replacing where the const variable is used with its value, to reduce the number of memory access operations.
Let's imagine that each variable is a little box where you can put numbers. So you have 3 boxes:
+---+ +---+ +---+
| 5 | | | | |
+---+ +---+ +---+
a b p
Now let's go over each statement and see what is happening.
int *p;
p= (int *) &a;
p is defined as a pointer, which is a type of variable that can hold the address of something in memory. In this case, it is assigned the address of variable a. So our boxes now look like this:
+---------------+
v |
+---+ +---+ +----+
| 5 | | | | &a |
+---+ +---+ +----+
a b p
p simply contains the memory address of a. You can print it with printf("%u", a), and you will see some number. That is the address of a.
b=a;
Here we are copying the value of a into b, so our boxes become:
+---------------+
v |
+---+ +---+ +----+
| 5 | | 5 | | &a |
+---+ +---+ +----+
a b p
*p= *p +1;
Using the *p syntax, we can dereference the pointer, that means that we can access the memory that p is pointing to (follow the arrow). In this case, *p will allow us to get or set the contents of the a variable. Our boxes now become like this:
+---------------+
v |
+---+ +---+ +----+
| 6 | | 5 | | &a |
+---+ +---+ +----+
a b p
printf(" value of p is = %d\n", *p);
Here you are again dereferencing p, meaning that we are getting the contents of the memory at address p. In our case, this will get the contents of the a variable which is 6.
printf(" value of b is = %d\n", b);
Looking at the b box, we can see that it contains 5.
printf(" value of a is = %d\n",a);
We modified a using the pointer. Looking at the a box, we can see that it contains the value 6.
We go line by line
const int a =5;int b;
In this line, variable b is defined as int and variable a is defined as const int, which means that its value is constant at all lower steps and is equal to 5.
int *p;
p= (int *) &a;
In these two lines, a variable called p is defined as a pointer int, whose value (must be an address from memory cells) is equal to the address of the variable a.
This means that both variables a and p point to a common memory cell.
In other words:
(*p == a) //IS TRUE. Both are equal to 5
and next line:
b = a;
That is, the value of the variable b is also equal to a, which is equal to 5
*p= *p +1;
In this line, a unit is added to the value corresponding to the address p.
We know that the variables a and p point to a common cell of memory.
In fact, this means that we indirectly added a unit to the variable a, which means that both variables have a value of (5 + 1).
And finally, the reason for the output of the last three lines is clear
The problem is entirely in the following line:
p= (int *) &a;
Without the type cast, the line would read:
p = &a;
The type of a is const int.
The type of p is int *.
It is obvious that the compiler should warn about discarding the const qualifier:
warning: assigning to 'int *' from 'const int *' discards qualifiers
[-Wincompatible-pointer-types-discards-qualifiers]
This demonstrates why you should always try to avoid explicit type casting (unless strictly necessary). The author of this code shot themselves in the foot. They introduced undefined behaviour and the obvious problem was hidden, because the warning was discarded or suppressed

Why should we use a pointer to store an address in C?

I was learning C language where I saw that pointers are variables that store the address of other variables. So I ran this code:
int x = 10;
int *p;
p = &x;
printf("%i\n", p);
Result: 6422292
Then I tried to do the same thing without using pointers, just using a variable to store the address:
int z = 10;
int v;
v = &z;
printf("%i", v);
Result: 6422282
Since we can use variables to store other variables' address, why do we use pointers at all?
Pointers are not integers. They may have integral representation, but they do not behave like integers and should not be treated like integers. Note that on platforms like x86_64 an int is not wide enough to store a pointer value.
Pointers are a distinct class of datatypes for storing the location of an object or function - they are an abstraction of a memory address, with additional type information. Remember, a data type isn't just about what values you can store, but also about what operations you can perform on those values. Pointer operations are distinct from integer operations. The + and - operators mean very different things for integer and pointer types. The unary * operator is not defined for integer types. The arithmetic * and / operators are not defined for pointer types.
And so on.
Pointers to different types are themselves different types and are not interchangeable. Pointer arithmetic (the basis of array subscripting) is based on the pointed-to type. That is, if cp is a char * pointing to a char object, then cp + 1 yields the location of the next char object immediately following. If ip is an int * pointing to an int object, then ip + 1 yields the location of the next int object immediately following:
+---+
c: | | <--- cp
+---+
| | <--- cp + 1
+---+
...
+---+
i: | | <--- ip
+---+
| |
+---+
| |
+---+
| |
+---+
| | <-- ip + 1
+---+
| |
+---+
| |
+---+
| |
+---+
...
This is what I mean about pointers not behaving like integers. They have their own distinct semantics.
C expects the operand of the unary * operator to have pointer type. If you try to deference an integer, even if that integer object stores a valid address value, the compiler will yell at you.
In case of integer, it looks like good, because address is itself integer, but try to do this with other data type like string , array and any struct . You will get the idea why we need pointer in C.

The good old beginnerkiller: Pointers

I am currently studying C and reached the point (haha...) where I am learning about pointers. I think I know a bit about them already and I think I get the concept of them.
If I have a pointer named "c" and an integer named "a" with the value of 5 and I do the following:
*c = a;
I set the value of the pointer c (because I am using the asterik symbol) to the value of a, which is 5. So *c is 5 after that and c is equal to the memory address of a - Correct?
What about the following then:
c = &a;
I just pass the memory address in which the value of a is stored to the pointer.
Are both operations equal? From my point of view they do the same - Is that correct?
*c = a;
You will end up with this:
+---+ +---+ +---+
| A | | C | | ? |
+---+ +---+ +---+
| 5 | | # | | 5 |
+---+ +-+-+ +-+-+
| ^
| |
+--------+
Howerver with:
c = &a;
you'll end up with:
+---+ +---+
| A | | C |
+---+ +---+
| 5 | | # |
+---+ +-+-+
^ |
| |
+---------+
So in in both cases, you'll have *c == 5, but what differs is what c points to.
Almost. Keep in mind that the first one you are saying: "take the portion of memory where 'c' points to and makes it equal 5". Therefore, you need to assign which portion of memory is that, before setting it to 5. So you actually have two different variables ('a' and the one 'c' points to).
In the second case you are just assigning 'c' to point to 'a'. So yea, you will again point to a value 5 but now you have only one variable 'a' and a pointer pointing to that same space of memory
If I have a pointer named "c" and an integer named "a" with the value
of 5 and I do the following:
*c = a; I set the value of the pointer c (because I am using the asterik symbol) to the value of a, which is 5. So *c is 5 after that
and c is equal to the memory address of a - Correct?
No, the contents of the variable that c is pointing to will get the value of the variable a. The pointer itself is not changed.
What about the following then:
c = &a; I just pass the memory address in which the value of a is
stored to the pointer.
This changes the pointer c itself to point to the variable a.
Are both operations equal? From my point of view they do the same - Is that correct?
No, the first changes the value of whatever c points to, the second one changes what the pointer points to.
An important difference is that the first (*c = a) requires that c is valid -- i.e. actually points to an object). The second one makes c a valid pointer, overwriting its previous value.
If you are using *c=a it will assign 5 to memory address where c is pointing, and if you change value of a it will not affected to value of c.
While if you use c=&a than c started to pointing to memory address of a and of you changed the value of a it will change the value where c is pointing(*c).

Reinitializing Pointers for C Language

I'm currently learning C Programming through Dan Gookin's book Beginning C Programming for Dummies.
One of the topic I'm currently reading is on the fact that arrays are in fact pointers. Dan attempted to prove that with the following code:
#include <stdio.h>
int main()
{
int numbers[10];
int x;
int *pn;
pn = numbers; /* initialize pointer */
/* Fill array */
for(x=0;x<10;x++)
{
*pn=x+1;
pn++;
}
pn = numbers;
/* Display array */
for(x=0;x<10;x++)
{
printf("numbers[%d] = %d, address %p\n",
x+1,*pn,pn);
pn++;
}
return(0);
}
My question is really with line 17. I realized that if I do not reintialize the pointer again as in line 17, the peek values of pointer pn being displayed at the second for loop sequence are a bunch of garbage that do not make sense. Therefore, I would like to know why is there a need to reintialize the pointer pn again for the code to work as intended?
An array is not a pointer, but C allows you to assign the array to a pointer of the type of the variable of the array, with the effect that that pointer will point to the first item in the array. That's what pn = numbers does.
pn is a pointer to an int, not to an array. It points to a single integer. When you increment the pointer, it just shifts to the next memory location. The shift it makes is the size of the type of the pointer, so int in this case.
So what does this prove? Not that an array is a pointer, but only that an array is a continuous block of memory that consists of N times the size of the type of your array item.
When you run the second loop, your pointer arrives at a piece of memory that doesn't belong to the array anymore, and so you get 'garbage' which is just the information which happens to exist at that location.
If you want to iterate over the array again by incrementing a pointer, you will have to reinitialize that pointer to the first item. The for loop does only do one thing, which is counting to 10. It doesn't know about the array and it doesn't know about the pointer, so the loop isn't going to automatically reset the pointer for you.
Since pn is incremented in the first loop, after the first loop is finished, pn will point to an address beyond the numbers array. Therefore, you must initialize pn to the beginning of the array before the second loop since you use the same pointer for printing the contents.
Because you have changed the address contained in pn in the statement pn++ in the following code snippet.
for(x=0;x<10;x++)
{
*pn=x+1;
pn++;
}
The pn pointer is being used to point into the numbers array.
The first for-loop uses pn to set the values, stepping pn throught the data element by element. After the end of the loop, pn points off the end of numbers (at a non-allocated 11th element).
For the second for-loop to work, i.e. to use pn to loop through numbers again by stepping through the array, pn needs to be moved to the front of the numbers array, otherwise you'll access memory that you shouldn't be looking at (non-allocated memory).
First arrays are not pointers. They decay to pointers when used in function calls and can be used (almost) the same.
Some subtle differences
int a[5]; /* array */
int *pa = a; /* pointer */
pa[0] = 5;
printf("%d\n", a[0]); /* ok it is the same here */
printf("address of array %p - address of pointer %p, value of pointer\n",
&a, &pa, pa); /* &a is the same as pa not &pa */
printf("size of array %d - size of pointer %d\n", sizeof(a), sizeof(pa));
sizeof(a) is here 5 * sizeof(int) whereas sizeof(pa) is the size of a pointer.
Now for your question:
After first loop, pn points to p[10] and no longer to p[0]. That's the reason why you must reset it.
Just to drive the point home, arrays are not pointers. When you declare numbers as int numbers[10], you get the following in memory:
+---+
numbers: | | numbers[0]
+---+
| | numbers[1]
+---+
...
+---+
| | numbers[9]
+---+
There's no storage set aside for a separate pointer to the first element of numbers. What happens is that when the expression numbers appears anywhere, and it isn't the operand of the sizeof or unary & operators, it is converted ("decays") to an expression of type "pointer to int", and the value of the expression is the address of the first element of the array.
What you're doing with pn is setting it to point to the first element of numbers, and then "walking" through the array:
+---+
numbers: | | <------+
+---+ |
| | |
+---+ |
... |
+---+ |
| | |
+---+ |
... |
|
+---+ |
pn: | | -------+
+---+
The expression pn++ advances pn to point to the next integer object, which in this case is the next element of the array:
+---+
numbers: | |
+---+
| | <------+
+---+ |
... |
+---+ |
| | |
+---+ |
... |
|
+---+ |
pn: | | -------+
+---+
Each pn++ advances the pointer until, at the end of the first loop, you have the following:
+---+
numbers: | |
+---+
| |
+---+
...
+---+
| |
+---+
... <------+
|
+---+ |
pn: | | -------+
+---+
At this point, pn is pointing to the object immediately following the end of the array. This is why you have to reset pn before the next loop; otherwise you're walking through the memory immediately following numbers, which can contain pretty much anything, including trap representations (i.e., bit patterns that don't correspond to a legal value for the given type).
Trying to access memory more than one past the end of an array invokes undefined behavior, which can mean anything from your code crashing outright to displaying garbage to working as expected.
During the fill array, the pointer pn is incremented and the data is placed on array. Same pointer variable used to print the array content. Since this reinitialise is done.

Different Pointer Arithmetic Results when Taking Address of Array

Program:
#include<stdio.h>
int main(void) {
int x[4];
printf("%p\n", x);
printf("%p\n", x + 1);
printf("%p\n", &x);
printf("%p\n", &x + 1);
}
Output:
$ ./a.out
0xbff93510
0xbff93514
0xbff93510
0xbff93520
$
I expect that the following is the output of the above program. For example:
x // 0x100
x+1 // 0x104 Because x is an integer array
&x // 0x100 Address of array
&x+1 // 0x104
But the output of the last statement is different from whast I expected. &x is also the address of the array. So incrementing 1 on this
will print the address incremented by 4. But &x+1 gives the address incremented by 10. Why?
x -> Points to the first element of the array.
&x ->Points to the entire array.
Stumbled upon a descriptive explanation here: http://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find
SO link: Why is arr and &arr the same?
In case 4 you get 0x100 + sizeof x and sizeof x is 4 * sizeof int = 4 * 4 = 16 = 0x10.
(On your system, sizeof int is 4).
An easy thumbrule to evaluate this is:
Any pointer on increment points to the next memory location of its base type.
The base type of &x here is int (*p)[4] which is a pointer to array of 4 integers.
So the next pointer of this type will point to 16 bytes away (assuming int to be 4 bytes) from the original array.
Even though x and &x evaluate to the same pointer value, they are different types. Type of x after it decays to a pointer is int* whereas type of &x is int (*)[4].
sizeof(x) is sizeof(int)*4.
Hence the numerical difference between &x and &x + 1 is sizeof(int)*4.
It can be better visualized using a 2D array. Let's say you have:
int array[2][4];
The memory layout for array is:
array
|
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
array[0] array[1]
| |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
If you use a pointer to such an array,
int (*ptr)[4] = array;
and look at the memory through the pointer, it looks like:
ptr ptr+1
| |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
As you can see, the difference between ptr and ptr+1 is sizeof(int)*4. That analogy applies to the difference between &x and &x + 1 in your code.
Believe it or not, the behaviour of your program is undefined!
&x + 1 is actually pointing to just beyond the array, as #i486's answer cleverly points out. You don't own that memory. Even attempting to assign a pointer to it is undefined behaviour, let alone attempting to dereference it.

Resources