Why ++(*p) changes the pointer value? - c++

If I have this code:
int A[5] = { 2, 1, 3, 55 };
int *p = A;
cout << ++(*p);
the result is 3 and the value of the first position of A is 3 also, why?
I mean, by hierarchy of operators () is more hierarchical than ++, then we would need operate *p first:
++(*p) => ++(2) => 3
with any change in A vector?

*p is not just "2", it's an lvalue, i.e. this "2" has a well-defined location.
The value at this location is modified by the ++ operator - by definition of the ++ operator.
If you don't want to modify the value, use + 1 instead: *p + 1.
In C/C++, lvalue is a value with a defined location in memory. This value can be changed - by an assignment, incremented, decrement.
For example,
int x = 0;
x = 1; // ok, x is an lvalue, assignment changes the value from 0 to 1
int *p = &x;
*p = 2; // ok, *p is an lvalue, assignment changes the value from 1 to 2
In contrast, an rvalue is a value without a defined location - for example, a result of an arithmetic operation. This value can't be assigned, incremented or decremented (it doesn't mean it can't be used in a larger expression).
For example,
int x = 0, y = 1;
(x + y) = 3; // compilation error, (x + y) is an rvalue
2++; // compilation error, 2 is an rvalue
Here's a pretty simple article explaining lvalues / rvalues: https://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c

The ++(*p) is the same as ++p[0] and ++A[0] All change the first element of the array.
Why ++(*p) changes the pointer value
It does not. The pointer value is value kept in the p. It is called "address" or "reference". It does not change.

It's worth noting the overuse of '*' in C++ which usually confuses novices.
Here:
int *p = A;
'*' means you are declaring p as a variable that can store a memory address (a pointer), and assigning the address of the first position of A (it's the same as &(A[0]) ).
Here:
++(*p)
' *' means you are looking into 'p' content (derreferencing the address of 'p' which is the same as the address of 'A[0]'). Then the '++' increments the value which reflects both.
Just to confirm, after this assignment (int *p = A;) print the values of 'p', 'A' and '&A[0]'.

Related

Can pointers be used for accessing any arbitrary area in memory?

I am extremely new to C++ and pointers.
#include <iostream>
using namespace std;
int main() {
char* c = "my name jeff";
int i = 0;
while (true) {
cout << *(c + i++);
}
return 0;
}
The output is "my name jeff" followed by a lot of random characters, occasionally making sense. Am I actually accessing memory in my computer ? Why can initialize a pointer from a string ?
From https://eel.is/c++draft/expr#add-4
When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
(4.1) If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
(4.2)
Otherwise, if P points to an array element i of an array object x with n elements ([dcl.array]),77 the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) array element
i
+
j
of x if
0
≤
i
+
j
≤
n
and the expression P - J points to the (possibly-hypothetical) array element
i
−
j
of x if
0
≤
i
−
j
≤
n
.
(4.3)
Otherwise, the behavior is undefined.
So, with "my name jeff" (which is of type const char[13] (with the extra '\0')), once you do c[14] you have UB.
First, a note about this line right here:
char* c = "my name jeff";
In modern C++, this should be a const instead:
const char* c = "my name jeff";
With that out of the way, the answer to your question is yes and no.
Yes in the sense that if you have some sort of pointer, C++ doesn't care what you put in it.
char * pointer = nullptr;
char a, b, c;
pointer = &a;
pointer = &b;
pointer = &c;
The pointer doesn't care what address is stored in it. It is arbitrary in that sense. As long as it is the same type, you're fine.
You can even do pointer arithmetic like this:
*(pointer + 1) = 1;
*(pointer + 2) = 2;
*(pointer + i) = i;
In most cases, this will usually at least compile and probably run. In theory, you could use this type of arithmetic to access any given address and see what data is stored there.
However, in practice, the answer is a big no. That is because accessing unallocated memory is undefined behavior in C++. If you're unaware, undefined behavior allows anything to happen, including crashing or printing weird characters.
So, if you have some array like this:
int arr[4] = {1,2,3,4};
int * pointer = arr;
std::cout << *(pointer + 7);
This is undefined behavior because only pointer + 3 is guaranteed to have allocated memory in it.
So, in short: Yes, you can theoretically reach any address you want with pointer arithmetic, but you can only access memory that has been allocated safely. So in practice, not really.

Trying to understand * and & in C++ [duplicate]

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 7 years ago.
I have a few questions. This isn't homework. I just want to understand better.
So if I have
int * b = &k;
Then k must be an integer, and b is a pointer to k's position in memory, correct?
What is the underlying "data type" of b? When I output it, it returns things like 0x22fe4c, which I assume is hexadecimal for memory position 2293324, correct?
Where exactly is memory position '2293324'? The "heap"? How can I output the values at, for example, memory positions 0, 1, 2, etc?
If I output *b, this is the same as outputting k directly, because * somehow means the value pointed to by b. But this seems different than the declaration of b, which was declared int * b = k, so if * means "value of" then doesn't mean this "declare b to the value of k? I know it doesn't but I still want to understand exactly what this means language wise.
If I output &b, this is actually returning the address of the pointer itself, and has nothing to do with k, correct?
I can also do int & a = k; which seems to be the same as doing int a = k;. Is it generally not necessary to use & in this way?
1- Yes.
2- There's no "underlying data type". It's a pointer to int. That's its nature. It's as data type as "int" or "char" for c/c++.
3- You shouldn't even try output values of memory which wasn't allocated by you. That's a segmentation fault. You can try by doing b-- (Which makes "b" point to the "int" before it actual position. At least, to what your program thinks it's an int.)
4- * with pointers is an operator. With any data type, it's another data type. It's like the = symbol. It has one meaning when you put == and another when you put =. The symbol doesn't necesarilly correlates with it meaning.
5- &b is the direction of b. It is related to k while b points to k. For example, if you do (**(&b)) you are making the value pointed by the value pointed by the direction of b. Which is k. If you didn't changed it, of course.
6- int & a = k means set the direction of a to the direction of k. a will be, for all means, k. If you do a=1, k will be 1. They will be both references to the same thing.
Open to corrections, of course. That's how I understand it.
In answer to your questions:
Yes, b is a pointer to k: It contains the address of k in the heap, but not the value of k itself.
The "data type" of b is an int: Essentially, this tells us that the address to which b points is the address of an int, but this has nothing to do with b itself: b is just an address to a variable.
Don't try to manually allocate memory to a specific address: Memory is allocated based of the size of the object once initialized, so memory addresses are spaced to leave room for objects to be allocated next to each other in the memory, thus manually changing this is a bad idea.
* In this case is a de-reference to b. As I've said, b is a memory address, but *b is what's at b's address. In this case, it's k, so manipulating *b is the same as manipulating k.
Correct, &b is the address of the pointer, which is distinct from both k and b itself.
Using int & a = k is creating a reference to k, which may be used as if it were k itself. This case is trivial, however, references are ideal for functions which need to alter the value of a variable which lies outside the scope of the function itself.
For instance:
void addThree(int& a) {
a += 3;
}
int main() {
int a = 3; //'a' has a value of 3
addThree(a); //adds three to 'a'
a += 2; //'a' now has a value of 8
return 0;
}
In the above case, addThree takes a reference to a, meaning that the value of int a in main() is manipulated directly by the function.
This would also work with a pointer:
void addThree(int* a) { //Takes a pointer to an integer
*a += 3; //Adds 3 to the int found at the pointer's address
}
int main() {
int a = 3; //'a' has a value of 3
addThree(&a); //Passes the address of 'a' to the addThree function
a += 2; //'a' now has a value of 8
return 0;
}
But not with a copy-constructed argument:
void addThree(int a) {
a += 3; //A new variable 'a' now a has value of 6.
}
int main() {
int a = 3; //'a' has a value of 3
addThree(a); //'a' still has a value of 3: The function won't change it
a += 2; //a now has a value of 5
return 0;
}
There are compliments of each other. * either declares a pointer or dereferences it. & either declares a (lvalue) reference or takes the address of an object or builtin type. So in many cases they work in tandem. To make a pointer of an object you need its address. To use a pointer as a value you dereference it.
3 - If k is a local variable, it's on the stack. If k is a static variable, it's in the data section of the program. The same applies to any variable, including b. A pointer would point to some location in the heap if new, malloc(), calloc(), ... , is used. A pointer would point to the stack if alloca() (or _alloca()) is used (alloca() is similar to using a local variable length array).
Example involving an array:
int array_of_5_integers[5];
int *ptr_to_int;
int (*ptr_to_array_of_5_integers)[5];
ptr_to_int = array_of_5_integers;
ptr_to_array_of_5_integers = &array_of_5_integers;

Int *t; and this t[*t] - Type definition

I'm working on updating a code of a server project since days.
I found a line that I cannot understand (which was commented)
First, I get :
int *t;
Then I got this (commented):
t[*t];
What's the type of this "t[*t]"
The type is an int lvalue. We have two parts:
*t // this is an int
t[ some int ] // this is standard array indexing
Or for a simple example:
int array[] = {1, 2, 3, 4};
int* t = array;
With that setup:
t[*t] == t[1] == 2
Or:
t[*t] = 7;
// now array[] holds {1, 7, 3, 4}
The type is int
*t is equivalent to t[0] as such your expression is equivalent to the follow:
t[*t] == t[t[0]] == t[offset] (if you consider offset = t[0])
By definition of the language, given that t is a pointer, the expression t[*t] is completely equivalent to the expression *(t + *t).
To analyze the type of that expression, let's look at it step for step, from the inside out. I'll replace each expression whole type was identified with «type».
Since t is of type int*, we have *(«int*» + *«int*»).
Dereferencing an int* gives an lvalue of type int. Therefore we get *(«int*» + «int»).
Now adding an integer to a pointer gives, again, a pointer of the same type, so the expression reduces to *«int*».
But that is, again, just the dereferencing of a pointer to int, and therefore the final type of the expression is lvalue int.
Sometimes code is estimated by the number of typed symbols. So I would write a more confusing code but with more characters like:)
( t + *t )[*t];
Relative to your example
*t is some integer stored in t that is *tis equivalent to t[0]. Thus in expression t[*t] there is used the pointer arithmetic
t + *t
or
t + t[0]
that gives some new pointer that then is dereferenced
*( t + *t )
The operator[] of int* always returns an int.
Since *t simply returns the first element of t, t[*t] is the element of tpointed to by the first element of t.
Example:
int *t;
t=new int[5];
for(int i=0;i<5;++i){
t[i]=i+1;
} // t now points to {1,2,3,4,5}
t[*t]; // <--- What does this evaluate to?
In this case t[*t] will be 2.
Because *t is 1, t[1] is the second element in the array, which is 2.

Behavior of 2D arrays

I have created a 2D array, and tried to print certain values as shown below:
int a[2][2] = { {1, 2},
{3, 4}};
printf("%d %d\n", *(a+1)[0], ((int *)a+1)[0]);
The output is:
3 2
I understand why 3 is the first output (a+1 points to the second row, and we print its 0th element.
My question is regarding the second output, i.e., 2. My guess is that due to typecasting a as int *, the 2D array is treated like a 1D array, and thus a+1 acts as pointer to the 2nd element, and so we get the output as 2.
Are my assumptions correct or is there some other logic behind this?
Also, originally what is the type of a when treated as pointer int (*)[2] or int **?
When you wrote expression
(int *)a
then logically the original array can be considered as a one-dimensional array the following way
int a[4] = { 1, 2, 3, 4 };
So expression a points to the first element equal to 1 of this imaginary array. Expression ( a + 1 ) points to the second element of the imaginary array equal to 2 and expression ( a + 1 )[0] returns reference to this element that is you get 2.
Are my assumptions correct or is there some other logic behind this?
Yes.
*(a+1)[0] is equivalent to a[1][0].
((int *)a+1)[0] is equivalent to a[0][1].
Explanation:
a decays to pointer to first element of 2D array, i.e to the first row. *a dereferences that row which is an array of 2 int. Therefore *a can be treated as an array name of first row which further decay to pointer to its first element, i.e 1. *a + 1 will give the pointer to second element. Dereferencing *a + 1 will give 1. So:
((int *)a+1)[0] == *( ((int *)a+1 )+ 0)
== *( ((int *)a + 0) + 1)
== a[0][1]
Note that a, *a, &a, &a[0] and &a[0][0] all have the same address value although they are of different types. After decay, a is of type int (*)[2]. Casting it to int * just makes the address value to type int * and the arithmetic (int *)a+1 gives the address of second element.
Also, originally what is the type of a when treated as pointer (int (*)[2] or int **?
It becomes of type pointer to array of 2 int, i.e int (*)[2]
A 2D-array is essentially a single-dimensional array with some additional compiler's knowledge.
When you cast a to int*, you remove this knowledge, and it's treated like a normal single-dimensional array (which in your case looks in memory like 1 2 3 4).
The key thing to recognize here is that the a there holds the value of the address where the first row is located at. Since the whole array starts from the same location as that, the whole array also has the same address value; same for the very first element.
In C terms:
&a == &a[0];
&a == &a[0][0];
&a[0] == &a[0][0];
// all of these hold true, evaluate into 1
// cast them if you want, looks ugly, but whatever...
&a == (int (*)[2][2]) &a[0];
&a == (int (*)[2][2]) &a[0][0];
&a[0] == (int (*)[2]) &a[0][0];
For this reason, when you cast the a to int *, it simply becomes 1-to-1 equivalent to &a[0][0] both by the means of type and the value. If you were to apply those operations to &a[0][0]:
(&a[0][0] + 1)[0];
(a[0] + 1)[0];
*(a[0] + 1);
a[0][1];
As for the type of a when treated as a pointer, although I am not certain, should be int (*)[2].

Increment operator on pointer of array errors?

I'm trying something very simple, well supposed to be simple but it somehow is messing with me...
I am trying to understand the effect of ++ on arrays when treated as pointers and pointers when treated as arrays.
So,
int main()
{
int a[4] = { 1, 4, 7, 9 };
*a = 3;
*(a+1) = 4;
*++a = 4; //compiler error
}
1: So at *(a+1)=4 we set a[1]=4; //Happy
But when *++a = 4;, I'd expect pointer a to be incremented one since ++ is precedent to * and then * kicks in and we make it equal to 4. But this code just does not work... Why is that?
Another problem:
int main()
{
int* p = (int *)malloc(8);
*p = 5;
printf("%d", p[0]);
*++p = 9; //now this works!
printf("%d", p[1]); //garbage
printf("%d", p[0]); //prints 9
}
2: Now *++p = 9; works fine but it's not really behaving like an array. How are two different? This is just incrementing p, and making it equal to 9. If I print p[0], it now prints 9 and I see that though can't access it via p[0] anymore, *(p-1) shows 5 is still there. So indexing a pointer with [0], where exactly does it point to? What has changed?
Thanks a lot all experts!
The array names is not modifiable lvalue so operation ++ is not applied hence ++a that try to modify a is compilation time error (where a is array name).
Note *(a + 1) and *a++ are not same, a + 1 is a valid instruction as it just add 1 but doesn't modify a itself, Whereas ++a (that is equvilent to a = a + 1) try to modify a hence error.
Note 'array names' are not pointer. Pointers are variable but array names are not. Of-course when you assign array name to a pointer then in most expressions array names decays into address of first element. e.g.
int *p = a;
Note p points to first element of array (a[0]).
Read some exceptions where array name not decaying into a pointer to first element?
An expression a[i] is equivalent to *(a + i), where a can be either a pointer or an array name. Hence in your second example p[i] is valid expression.
Additionally, *++p is valid because because p is a pointer (a variable) in second code example.
int a[4] = { 1, 4, 7, 9 };
int *pa=a;
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, sopa=a and pa++ are legal. But an array name is not a
variable; constructions like a=pa and a++ are illegal
int* p = (int *)malloc(8);
Don't cast result of malloc()
Use index with pointer
p[1]=9; // p[1]==*(p+1)