Pre/Post Increment Pointers in C++ - c++

*(p1++)
int array[10] = {1,2};
int *p1 = array;
*p1=24;
*p1= *(p1++);
for (int i : array)
cout << i << " ";
Output is 24 24
*(++p1)
int array[10] = {1,2};
int *p1 = array;
*p1=24;
*p1= *(++p1);
for (int i : array)
cout << i << " ";
Output is 24 2
It seems like this is the exact opposite of doing increment with values. Can someone explain what is going on here? Thanks!

There is an undefined behavior in
*p1 = *(p1++);
because, quoting ยง1.9/15:
If a side effect on a scalar
object is unsequenced relative to either another side effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
Side effect here is an increment of p1 and value computation is a computation of address using p1.
So you shouldn't rely on the exact outcome of your examples.

*p1= *(p1++);
This just doesn't make sense. The semantic meaning of this operation is different depending on which side of the = is evaluated first. So there's no way you can make any sense out of it.

For *(p1++):
*p1 = *(p1++)
p1++ will increment p1 to point to index 1 in the array, and return the previous value of p1 (index 0). So *(p1++) will return 24, and *p1 will now equal 2. *p1 is then assigned that return value (24), so the array will be {24,24}.
for *(++p1):
*p1 = *(++p1)
++p1 will increment p1 to point to index 2 in the array, and return the current value of p1 (index 1). So *(++p1) will return 2, and *p1 will now equal 2. *p1 is then assigned that return value (2), which is the original value at the index of p1 (1), so the array will remain {24,2}

Related

pointers in C++ (need overview)

int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue;
p2 = &secondvalue;
*p1 = 10; //line 1
*p2 = *p1; //line 2
p1 = p2; //line 3
*p1 = 20;
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
My Analysis of this code:
p1 points to the first value and p2 points to the second value. Now, p1 points to value 10. My first question is :
Does this means that first value now stores 10. (line 1)
According to me, line 2 means that p2 and p1 point to the value stored at the address of the second value. AM I correct or wrong?
Lastly, I have no clue of line 3. So, need some help over there too.
Answer 1: p1 still points to firstValue, but the value of firstValue is now changed to 10
Answer 2: in line 2, secondValue is assigned the value of firstValue.
Answer 3: line 3 is assigning the pointer of secondValue to the p1, so any changes in *p1 will reflect in the changed value of secondValue.
Hope this helps.
Does this means that first value now stores 10. (line 1)
Yes.
line 2 means that p2 and p1 point to the value stored at the address of the second value.
No. It means that the value p2 points to gets a copy of the value that p1 points to. It is the equivalent of saying secondvalue = firstvalue; because p2 points to secondvalue and p1 points to firatvalue and the * in *p1 or *p2 in this context accesses the value the pointer points to.
I have no clue of line 3.
This says that p1 will now point at the same place that p2 points to. So both p1 and p2 point to secondvalue.
Forget syntax for a second and think about what those objects are.
A memory location has exactly two properties, location and content.
int firstvalue; reserves a memory location (its size does not matter here).
firstvalue = 5; stores a value there.
firstvalue is a label associated with the memory address, &firstvalue is that address.
A pointer is a variable containing an address, dereferencing with '*' gives you the content at that address.
So now
p1 = &firstvalue; //address of firstvalue stored in pointer p1
p2 = &secondvalue; // same thing for p2 and secondvalue
*p1 = 10; //line 1: value 10 to variable pointed to by p1 i.e. firstvalue
*p2 = *p1; //line 2: copy firstvalue to secondvalue
p1 = p2; //line 3: now both point to secondvalue
Ok?
Lets understand what is a pointer - Pointer is storage of address it does not store value itself in light of it lets analyze the code line by line
1) Line 1 - Defined two variables (space to hold value)
2) Line 2 - Defined two pointers (space to hold address)
3) Line 4 & 5 - assigned address of the variables to pointers p1 & p2 now p1 points to location where value 5 is stored and p2 points to a location where 15 is stored
4) Line 6 - Value 10 is stored at the location p1 is pointing this means value of the variable firstvalue is changed from 5 to 10
5) Line 7 - Value of the location pointed by p1 is copied to location pointed by p2. Now both firstvalue and secondvalue is same which is 10
6) Line 8 - Value of the p2 pointer (which is address of secondvalue variable) is assigned to p1. now p1 and p2 both points to secondvalue variable
7) Line 9 - Assigned value 20 to the location pointed by pointer p1 which is now secondvalue variable
Result - both output will show value 20 as both pointers are now pointing to secondvalue variable and it is update to 20 at Line number 9
There you go...
#include <iostream>
using namespace std;
int main()
{
int firstvalue = 5, secondvalue = 15;
int * p1, *p2;
p1 = &firstvalue;
p2 = &secondvalue;
cout << "firstvalue address: ," << &firstvalue << "p1 address: ," << p1 << "p1 Value " << *p1 << endl;
*p1 = 10; //line 1
*p2 = *p1; //line 2
cout << "p1 Value " << *p1 << "p2 Value " << *p2 << endl;
p1 = p2; //line 3
cout << "p1 address: ," << p1 << "p2 address: ," << p2 << endl;
*p1 = 20;
cout << "p1 value: " << *p1 << endl;
return 0;
}
output:
firstvalue address: 0115FA74,p1 address: 0115FA74,p1 Value 5
p1 Value 10, p2 Value 10
p1 address: 0115FA68,p2 address: 0115FA68
p1 value: 20
Sorry, but your analysis is incorrect.
Starting with the first part of your code
int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue;
p2 = &secondvalue;
and your analysis of it
p1 points to the first value and p2 points to the second value.
Your analysis is roughly correct. I'll give a slightly more complete description.
p1 is a variable of type int * (i.r. a pointer to an int). The assignment p1 = &firstvalue assigns the value of p1 to be the address of the variable firstvalue. This is sometimes said to mean that the pointer p1 is assigned to point at firstvalue.
The same description applies to p2 and secondvalue.
Now, for the next statement
*p1 = 10; //line 1
and your analysis of it
Now, p1 points to value 10.
This is incorrect. p1 does not point to the value 10.
The statement, *p1 = 10 assigns the value 10 to the result of *p1. *p1 is a reference to whatever p1 points at, which (as per above) is firstvalue. Accordingly, the assignment *p1 = 10 has the effect of assigning firstvalue to the value 10.
This brings us to your first question (albeit one you wrote without a question mark).
Does this means that first value now stores 10. (line 1)
If by "first value" you mean "the variable named firstvalue", the answer here is "yes".
Now, we come to the next code statement
*p2 = *p1; //line 2
and your analysis
According to me, line 2 means that p2 and p1 point to the value stored at the address of the second value. AM I correct or wrong?
You are completely and utterly wrong here.
To better understand, let's break the statement into parts. *p1 obtains a reference to the variable pointed to by p1 - which is firstvalue (which has a value 10). *p2 obtains a reference to the variable pointed to by p2 - which is secondvalue. The assignment *p2 = *p1 therefore has the same effect as secondvalue = firstvalue.
p1 still points at (contains the address of) firstvalue. Similarly, p2 still points at secondvalue. Both variables firstvalue and secondvalue have the value 10.
Now we come to line 3
p1 = p2; //line 3
And your observation about it it
Lastly, I have no clue of line 3. So, need some help over there too.
Uh hu.
p2 is a pointer, and its value is &secondvalue - the address of secondvalue. The assignment p1 = p2 assign the value of p1 to equal the value of p2. This means that p1 and p2 both contain the value &secondvalue. (Or that both the pointers p1 and p2 point to secondvalue).
A consequence is that
*p1 = 20;
has the effect of assigning secondvalue to have the value 20. firstvalue is unaffected, and still contains the value 10.

Value Of Pointers

In my book, it says Pointers are addresses and have a numerical value. You can print out the value of a pointer as cout << (unsigned long)(p)
Write code to compare p,p+1,q, and q+1. Explain the results, Im not sure what the book wants me to so here's what I have. Does anyone Know if I am doing this right
int num = 20;
double dbl = 20.0;
int *p = &num;
double *q = &dbl;
cout << (unsigned long)(q) << endl;
q = q + 1;
cout << (unsigned long)(q) << endl;
cout << (unsigned long)(p) << endl;
p = p + 1 ;
cout << (unsigned long)(p) << endl;
Assuming it's the pointer arithmetic you have problems with, let my try to to show how it's done in a more "graphical" way:
Lets say we have a pointer variable ptr which points to an array of integers, something like
int array[4] = { 1234, 5678, 9012, 3456 };
int* ptr = array; // Makes `ptr` point to the first element of `array`
In memory it looks something like
+------+------+------+------+
| 1234 | 5678 | 9012 | 3456 |
+------+------+------+------+
^ ^ ^ ^
| | | |
ptr ptr+1 ptr+2 ptr+3
The first is technically ptr+0
When adding one to a pointer, you go to the next element in the "array".
Perhaps now you start to see some similarities between pointer arithmetic and array indexing. And that is because there is a common thread here: For any pointer or array p and valid index i, the expression p[i] is exactly the same as *(p + i).
Using the knowledge that p[i] is equal to *(p + i) makes it easier to understand how an array can be used as a pointer to its first element. We start with a pointer to the first element of array (as defined above): &array[0]. This is equal to the expression &*(array + 0). The address-of (&) and dereference (*) operators cancel out each, leaving us with (array + 0). Adding zero to anything can be removed as well, so now we have (array). And finally we can remove the parentheses, leaving us with array. That means that &array[0] is equal to array.
You do it right, if you want to print the decimal representation of the addresses your pointers point to.
If you wonder, why the results are such, you need to learn pointer arithmetic. If you add 1 to any pointer, it's address will be increased by sizeof(<type>), where type is the type of the variable your pointer points to.
So that, if you have a pointer to int and increment it, the address will be increased by sizeof(int), which is, most likely, four.

Increment, preincrement and postincrement

Help me to resolve this please. The steps that follows that expressions are:
//Expression
offSpring1[m1++] = temp1;
//Steps:
1.- increment m1
2.- assign temp1 to offSpring
I have always thought that the expression inside the brackets was the first to be done. But now I am confuse. So if a write this:
//Expression
offSpring1[++m1] = temp1;
//Steps would be:
1.- assign temp1 to offSpring
2.- increment m1
If the steps would be the same as first ones, what is the difference between i++ and ++i?
int i = 0;
std::cout << i++ << std::endl;
std::cout << i << "\nreset" << std::endl;
i = 0;
std::cout << ++i << std::endl;
std::cout << i << std::endl;
output:
0
1
reset
1
1
i++ returns the value as it currently stands in the expression, then increments the variable.
++i will increment the variable, then return the value to use in the current expression.
offSpring1[m1++] = temp1;
is
offSpring1[m1] = temp1;
m1 += 1;
and
offSpring1[++m1] = temp1;
is
m1 += 1;
offSpring1[m1] = temp1;
j = ++i is the same as i = i+1; j = i;
j = i++ is the same as j = i; i = i+1;
Just run these two different test programs to understand the difference between the post-increment and the pre-increment operators
For ++i (pre-increment)
int main()
{
int* offSpring = calloc(20,sizeof(int));
int m1 =1;
offSpring[++m1] = 10;
printf("%d,%d",offSpring[m1],m1);
}
In the first one you will get 10 as the value of offSpring[m1].
Why? Because this is the pre-increment operator which means that first m1 gets incremented and the the rest gets evaluated.
For i++(post-increment)
int main()
{
int* offSpring = calloc(20,sizeof(int));
int m1 =1;
offSpring[m1++] = 10;
printf("%d,%d",offSpring[m1],m1);
}
In the second because the post-increment operator is used you will get a 0 value since you are first assigning 10 to offSpring[m1] and then m1 gets incremented.
offSpring1[m1++] = temp1; doesn't do what you said.
assign temp_m1 = m1.
increment m1.
index offSpring1[temp_m1]
assign temp1 into indexed value.
On the other hand offSpring1[++m1] = temp1; works like this:
increment m1.
index offSpring1[m1]
assign temp1 into indexed value.
Even though postfix increment is the first to be evaluated in your first example, its value is the original value of the variable being incremented.
offSpring1[m1++] = temp1;
So even though m1 is incremented before array idexing, the value of temp1 is assigned at position m1 - 1.
There are two aspects to an expression (or sub-expression): its value,
and its side effects. The value of i ++ is the value of i; the
value of ++ i is the value i + 1, converted to the type of i.
This is the value used in the expression. The side effects of both is
to increment the variable i. This may occur at any time after the
preceding sequence point and before the next. Supposing i is a global
variable, and you write something like:
i = 0;
f()[i ++] = g();
f()[++ i] = g();
The standard says nothing about whether the value of i seen in f()
or g() is that before the incrementation, or after. In neither case.
All the standard says is that the effects of the incrementation will
take place after the start of the full expression (but perhaps as the
first thing in the full expression) and before the end of it. (And that
they won't be interleaved with a function call, so that if f()
reads i twice, it is guaranteed to see the same value.)
Unfortunately, in those 2 code snippets you've posted there, there's no guaranteed order of evaluation. If your expressions are inappropriate, more or less anything could happen.
To start with the difference between a++ and ++a:
a++ will increment a but the expression using it will see the value of a before the increment
++a will increment a, and the expression using it will see the incremented value.
List item
with
buffer[a++] = b;
the compiler can decide to do the ++ at any point within the expression. Thus if 'b' is actually an expression involving a, you can get different results on different compilers. Both of the following would be valid:
get the value of a;
increment a
work out where buffer[old value] points to
evaluate b
store b
or this
evaluate b;
work out where buffer[a] points to
store b
increment a
if 'b' should happen to involve a, those 2 implementations would produce different results. Both are valid.
It works precisely the opposite of what you described:
offSpring1[m1++] = temp1 is the same as
offSpring[m1] = temp1; m1 = m1 + 1;
OffSpring1[++m1] = temp1 is the same as
m1 = m1 + 1; OffSpring1[m1] = temp1;
Prefix notation increments before evaluating the expression
Postfix notation increments after evaluating the expression
The description of the first is the correct description for the second. The correct description of the first is very similar, you just need a "copy current value of m1" step added before the others.
But you do have a distinct lack of sequence points here, if m1 has a primitive type. The rules change somewhat between C++03 and C++11.
If m1 has a user-defined type, then there are function calls involved which influence sequencing.
This code
offSpring1[m1++] = temp1;
performs the following (if m1 is a primitive type):
auto const old_m1(m1);
auto const new_m1(old_m1 + 1);
auto& lhs(offSpring[old_m1]);
parallel { lhs = temp1; m1 = new_m1; }
This code
offSpring1[++m1] = temp1;
is exactly the same except that lhs is bound using new_m1 instead of old_m1.
In either case, it is unspecified whether lhs is written to before or after m1.
If m1 is not a primitive type, it looks more like:
auto const& index = m1.operator++(0); // one argument
auto& lhs = offSpring.operator[](index);
lhs = temp1;
vs
auto const& index = m1.operator++(); // no arguments
auto& lhs = offSpring.operator[](index);
lhs = temp1;
In both these cases, the change to m1 is definitely made before the write to lhs.

Not Understanding Pointer Arithmetic with ++ and --

So, I am learning about pointers via http://cplusplus.com/doc/tutorial/pointers/ and I do not understand anything about the pointer arithmetic section. Could someone clear things up or point me to a tutorial about this that I may better understand.
I am especially confused with all the parentheses things like the difference between *p++,(*p)++, *(p++), and etc.
*p++
For this one, ++ has higher precedence then * so it increments the pointer by one but retrieves the value at the original location since post-increment returns the pointer and then increments its value.
(*p)++
This forces the precedence in the other direction, so the pointer is de-referenced first and then the value at that location in incremented by one (but the value at the original pointer location is returned).
*(p++)
This one increments the pointer first so it acts the same as the first one.
An important thing to note, is that the amount the pointer is incremented is affected by the pointer type. From the link you provided:
char *mychar;
short *myshort;
long *mylong;
char is one byte in length so the ++ increases the pointer by 1 (since pointers point to the beginning of each byte).
short is two bytes in length so the ++ increases the pointer by 2 in order to point at the start of the next short rather than the start of the next byte.
long is four bytes in the length so the ++ increases the pointer by 4.
I found useful some years ago an explanation of strcpy, from Kernighan/Ritchie (I don't have the text available now, hope the code it's accurate): cpy_0, cpy_1, cpy_2 are all equivalent to strcpy:
char *cpy_0(char *t, const char *s)
{
int i = 0;
for ( ; t[i]; i++)
t[i] = s[i];
t[i] = s[i];
i++;
return t + i;
}
char *cpy_1(char *t, const char *s)
{
for ( ; *s; ++s, ++t)
*t = *s;
*t = *s;
++t;
return t;
}
char *cpy_2(char *t, const char *s)
{
while (*t++ = *s++)
;
return t;
}
First you have to understand what post increment does;
The post increment, increases the variable by one BUT the expression (p++) returns the original value of the variable to be used in the rest of the expression.
char data[] = "AX12";
char* p;
p = data;
char* a = p++;
// a -> 'A' (the original value of p was returned from p++ and assigned to a)
// p -> 'X'
p = data; // reset;
char l = *(p++);
// l = 'A'. The (p++) increments the value of p. But returns the original
value to be used in the remaining expression. Thus it is the
original value that gets de-referenced by * so makeing l 'A'
// p -> 'X'
Now because of operator precedence:
*p++ is equivalent to *(p++)
Finally we have the complicated one:
p = data;
char m = (*p)++;
// m is 'A'. First we deference 'p' which gives us a reference to 'A'
// Then we apply the post increment which applies to the value 'A' and makes it a 'B'
// But we return the original value ('A') to be used in assignment to 'm'
// Note 1: The increment was done on the original array
// data[] is now "BXYZ";
// Note 2: Because it was the value that was post incremented p is unchaged.
// p -> 'B' (Not 'X')
*p++
Returns the content, *p, an then increases the pointer's value (postincrement). For example:
int numbers[2];
int *p;
p = &numbers[0];
*p = 4; //numbers[0] = 4;
*(p + 1) = 8; //numbers[1] = 8;
int a = *p++; //a = 4 (the increment takes place after the evaluation)
//*++p would have returned 8 (a = 8)
int b = *p; //b = 8 (p is now pointing to the next integer, not the initial one)
And about:
(*p)++
It increases the value of the content, *p = *p + 1;.
(p++); //same as p++
Increases the pointer so it points to the next element (that may not exist) of the size defined when you declared the pointer.

Pointer to pointer array understanding problem

This is probably a stupid question, but I don't understand why this works:
int** test = new int*[7];
int x = 7;
*(test+1) = &x;
cout << (**(test+1));
test is a pointer to a pointer right? The second pointer points to the array, right?
In my understand I would need to dereference the "test" pointer first to get to the pointer that has the array.
(*test) // Now I have int*
*((*test) + 1) // to access the first element.
Where is my faulty thinking?
int** test = new int*[7];
+------++------++------++------++------++------++------+
| int* || int* || int* || int* || int* || int* || int* |
+------++------++------++------++------++------++------+
is the equivalent of an array with int pointers:
int* test[0]
int* test[1]
...
int* test[6]
this
int x = 7;
*(test+1) = &x;
+------++------++------++------++------++------++------+
| int* || &x || int* || int* || int* || int* || int* |
+------++------++------++------++------++------++------+
is the same as
int x = 7;
test[1] = &x
so now one of the pointers in your original array is pointing the memory location of x
cout << (**(test+1));
is the same as
cout << *test[1]
which is the value of x (==7) and which both test[1] and &x point to.
Is your misunderstanding that you think you have created a pointer to an array of 7 int? You haven't. You actually have created an array of 7 pointers to int. So there is no "second pointer" here that would point to an array. There is just one pointer that points to the first of the 7 pointers (test).
And with *test you get that first pointer which you haven't initialized yet, though. If you would add 1 to that, you would add 1 to some random address. But if you add 1 to test you get a pointer that points to the second pointer of the array. And dererencing that you get that second pointer, which you did initialize.
What you describe would be achieved by a different syntax
typedef int array[7];
array* test = new int[1][7];
// Note: "test" is a pointer to an array of int.
// There are already 7 integers! You cannot make it
// point to an int somehow.
*(*test + 1) = 7;
int *p1 = *test
int i1 = *(p1 + 1); // i1 is 7, second element of the int[7]
delete[] test;
Without using the typedef, this looks like the following
int(*test)[7] = new int[1][7];
That is, you have created a one-element array, where the element-type of that is a 7-element array of int. new gives you a pointer back to that array. Note that the parenthesis is important: The * has less precedence than the [7], so otherwise this would be taken as an array of 7 pointer to integers.
Suppose that
test[0] = 0x12345678; // some pointer value
test[1] = 0x23456789; // some pointer value
*test = 0x12345678;
*test + 1 is now 0x12345678 + 1 = 0x12345679;
* or dereference operator has higher precedence than binary +). So the expression is evaluated in that order.
However what you wanted for is to get to test[0] = 0x23456789;
So the correct expression to get to test[1] = (*(test + 1))
In general arr[i] is *(arr + i)
EDIT 2:
given
int buf[10] = {0, 1, 2};
int *p = buf;
buf[0] == p[0] == *(p + 0) equal to 0.
Note that it is perfectly fine to use array access syntax with the lvalue expression p even if it is not an array type. In fact the expression buf[0] is internally translated by the compiler to *(buf + 0) as well.
The expression *(test + 1) is equivalent to test[1], so your code could be rewritten thus:
int** test = new int*[7];
int x = 7;
test[1] = &x;
cout << *test[1];
Since test[1] obviously points to x, *test[1] is 7.
Just to be clear, the expression **(test + 1) is simply equivalent to *(*(test + 1)), which is in turn equivalent to *test[1].