Incrementing pointers in C++ - c++

Why are the two following code segments not equivalent?
void print (char* s) {
if (*s == '\0')
return;
print(s+1);
cout << *s;
}
void print (char* s) {
if (*s == '\0')
return;
print(++s);
cout << *s;
}

The ++ operator increments the pointer value, but then returns the original value ... so print(s++) will print the value of s before the increment, since even though it adds a value of 1 to s, making the value stored at s equal to s+1, it still returns the original value of s as the result of the operation. On the otherhand print(s+1) prints the value after the increment, but very importantly does not modify the original value of s. So the result of the statement s+1 is just a new temporary pointer value ... the original value of s is not modified.
Furthermore, since you've incremented and changed the value of s with the ++ operator, when you call cout, you're now printing the value to wherever the new pointer is pointing (this could cause a crash or segmentation fault if you're not careful and there's no user accessible memory at the new memory location s is pointing to). With s+1, the value of s remains unmodified, so the result of cout will be to wherever s was originally pointing.
Edit:
As Michael points out, this is actually a recursive function, so the second example simply keeps calling print() with the same argument, since as mentioned before, the returned value from s++ is the original value of s. That means you'll end up with a stack overflow at some point and just crash unless the value that s pointed to was already the NULL character.

Since it looks like the OP changed print(s++) to print(++s), which is hugely different, here's an explanation for this new version.
In the first example, you have:
print(s+1);
cout << *s;
s+1 does not modify s. So if s is 4, and you print(s+1), afterwards s will still be 4.
print(++s);
cout << *s;
In this case, ++s modifies the local value of s. It increments it by 1. So if it was 4 before print(++s), it will be 5 afterwards.
In both cases, a value equivalent to s+1 would be passed to the print function, causing it to print the next character.
So the difference between the 2 functions is that the first one will recursively print character #0, then 1, 2, 3, ..., while the second function prints 1, 2, 3, 4, ... (it skips the first character and prints the "\0" afterwards).
Example:
For the s+1 version, print("hello") will result in h e l l o
For the ++s version, print("hello") will result in e l l o \0

Both of the expressions s++ and s+1 are to do with increasing the position of the pointer itself, not the value contained at the pointer locations
The value of s++ is just s, and the value of s+1 is, well, one position further on than s!
The value of s after executing s++ is one position further on than it was before. After using s+1, the value of s is unchanged.
Therefore the order they print out the letters is reversed!

I will try to explain an example of pre and post increment from which you can solve the question posted yourself.
#include <iostream>
void foo(int num)
{
std::cout << num << "\n" ;
}
int main()
{
int number = 10 ;
foo( number++ ) ;
foo( ++number ) ;
foo( number + 1 ) ;
getchar() ;
return 0 ;
}
Output:
10
12
13
Why 10?
foo( number++ ) ;
Post-increment operation is done on number. Meaning, value of number is first passed to foo and then the value of number is incremented upon foo return. So, after function return, number is 11.
Why 12?
foo( ++number ) ;
Pre-increment operation is done on number. Meaning, before even call to foo, the value of number is incremented to 12. And then it is passed to foo. So, even after the function return, number is still 12.
Why 13?
It's just straight forward. Value of number is not modified but passed a value adding 1 to the value of number. In this process, number is not modified. So, even after function return, number is still 12.
Hope this helps to solve the problem yourself ( though in your case it is paper-pencil exercise ) :)

Related

Why adding "variable + 1" doesn't increment its value by one for every loop in a for loop? (C++)

I'm having a hard time understanding why using a increment operator in a for loop in C++ has a different result than doing 'variable' + 1. The variable in the second case simply isn't remembered after each iteration of the loop:
Take the following code:
#include <iostream>
int main(){
int a{0};
for (int i = 0; i < 5; i++){
std::cout << ++a;
}
return 0;
}
It outputs as expected:
12345
However, if I instead replace ++a with a + 1:
#include <iostream>
int main(){
int a{0};
for (int i = 0; i < 5; i++){
std::cout << a + 1;
}
return 0;
}
I get:
11111
Even if I make the 'a' variable static:
static int a{0};
It still outputs 11111.
Why doesn't 'a + 1' preserve its value after every loop? What would I need to do if I wanted to preserve its value after every iteration without using ++ (for instance, with another operation like a * 2)?
Why doesn't 'a + 1' preserve its value after every loop?
a + 1 is an expression that doesn't assign anything to a. That is a is not affected in any way. This means when you do just a + 1, the value of a is still 0(the old value).
On the other hand ++a has the same effect as:
v---------->assignment done here implicitly
a = a+1
In the above expression ++a, the value of is incremented by 1 so that the new value of a is now 1.
++a is equivalent to the assignment a= a + 1 (or a+= 1). The expression a + 1 alone does not modify a.
C++ will allow you to write std::cout << (a= a + 1);.
a++ is not the same thing as a+1 but as a=a+1.
What's the difference?
Well:
a+1 contains the value, which is one higher than the value of a.
a=a+1 means that, in top of this, this value gets assigned to the variable a, which means something like "replace a by its value plus one".
This gives following possibilities (I also show the difference between a++ and ++a):
int a=3;
cout<<a+1; // output : 4. Value of 'a' equals 3.
cout<<a+1; // output : 4. Value of 'a' equals 3.
cout<<a+1; // output : 4. Value of 'a' equals 3.
int a=3;
cout<<a++; // output : 3. Value of 'a' becomes 4 after having shown it on screen.
cout<<a++; // output : 4. Value of 'a' becomes 5 after having shown it on screen.
cout<<a++; // output : 5. Value of 'a' becomes 6 after having shown it on screen.
int a=3;
cout<<++a; // output : 4. Value of 'a' becomes 4 before showning it on screen.
cout<<++a; // output : 5. Value of 'a' becomes 5 before showning it on screen.
cout<<++a; // output : 6. Value of 'a' becomes 6 before showning it on screen.
Conceptually, the built-in arithmetic operators like + and * evaluate their operands, perform the respective operation with the thusly obtained values, and create a temporary object that contains the result.
The operands, one of which is your a, are only read from, not written to. That is more obvious when you consider that + is commutative, that is, its operands can be swapped without affecting the result: a+1 is by definition the same as 1+a, and clearly you cannot write anything back to the immediate value 1.
Generally, as you certainly know, = is used in C and C++ to write a value to a variable. C, and by means of ancestry also C++, provide shortcuts to write back the result of certain operations to one of their operands: it's the combination of the operator and the assignment =, for example a += 1. Like all assignments, this one is an expression (that is, it has a value) which has the value of the variable after the operation and assignment. Like all other expressions, you can use it as a subexpression, even though that's not very common: cout << (a += 1); would achieve the desired effect (the parentheses are necessary because assignment has about the lowest operator precedence). Because incrementing (and decrementing) by one is so very common, C and C++ have a shortcut for the shortcut: ++a is the same as a+=1, so that one would typically write cout << ++a; (as a side effect obviating the need for parentheses).

Palindrome mystery: Why an array of size 3 ends up being printed with 5 elements?

#include <iostream>
#include <cstring>
using namespace std;
int main(){
char a[] = "abc";
char b[2];
for(int i = 0,k = 2;i < 3;i++,k--){
b[k] = a[i];
cout << i << " " << k << endl;
}
if(strcmp(a,b) == 0){
cout << "palindrome";
}else{
cout << "no palindrome" << endl;
}
cout << "a: " << a << endl;
cout << "b: " << b << endl;
return 0;
}
output:
0 2
1 1
2 0
no palindrom
a: abc
b: cbabc
I don't understand why b array ends up with 5 elements, when the array holds only 3. Additionally, the loop loops only 3 times and this is the output I get.... A mystery.
You have an out-of-bounds array access and also need to be conscious of null-terminating your strings!
Specifically, char b[2]; gives you an array with exactly 2 chars, so only b[0] and b[1] are valid. You also need to account for the null character that should terminate all C-style strings. So to hold "cba" for example you need 4 elements. You can also see this if you print sizeof(a) (should be 4: 'a', 'b', 'c', '\0').
Basically, your program elicits undefined behavior (UB). The simple fix is to make b bigger (the same size as a, which is 4 in this case). The more complete answer is to manage your array lengths more carefully and look at the safer "n" versions of the C manipulation functions such as strncmp
Edit: to be complete, you have 2 sourced of UB. The first is in line b[k] = a[i] when k == 2 because again you have only allocated b[0] and b[1]. The second is when you call strcmp since b has not been properly null-terminated and strcmp will happily read past the array bounds, which it doesn't know.
b is not terminated by a null character (\0), so any string operation on it (like strcmp, or even just printing it with cout runs over until it happens to hit such a character somewhere in the memory. In other words, you are witnessing undefined behavior.
Strictly speaking you have undefined behaviour and any observed behaviour (wrong or seemingly partially correct) is explained by that.
For details and solutions see the other answers.
End of answer.
Now lets look at a speculation on why you might in your environment end up with specifically the output you observe.
Assumption, the memory for your arrays
char a[] = "abc";
char b[2]
looks like an often seen habit of linkers of how to arrange variables:
b[0] non-initialised
b[1] non-initialised
a[0] = 'a'
a[1] = 'b'
a[2] = 'c'
a[3] = '\0'
Note the four (not three) elements of a and the terminator 0.
Your loop, right in the first iteration, attempts to write to the non-existing b[2].
This is already what causes undefined behaviour. Clean discussion ends here.
Let's continue speculating.
Your loop unintentionally writes one place beyond the existing b[1] and ends up clobbering a[0]. By chance it writes the value which happens to be already there, so no change there.
Your loop continues to write, now to existing entries of b.
The speculated result is
b[0] = 'c
b[1] = 'b'
a[0] = 'a' = 'a'
a[1] = 'b'
a[2] = 'c'
a[3] = '\0'
and the loop ends.
Then you try to output a and b.
This is done by outputting all characters found consecutively from the start of the arrays, until a terminator 0 is found.
For a this (luckily in case of the "a") is "abc\0", all from a.
For b this is "bc" from b, followed (on the search for a 0) by "abc\0" from a.
Note that the seemingly correct "a" already is incorrectly from a, not from b.
Ok, when debugging this you can check for address of b[2].
In gdb:
(gdb) p &b[1]
$8 = 0x7fffffffdfe3 "\377abc"
See? If b was null terminated it would start with '\0', but it doesn't, you tell the compiler to use 2 spaces for b. When asked the debugger what's the address of last b character b[1], it not only tells the address, it also shows the char* value represented. As b is a non null terminated (my compiler didn't initialize it), it will continue beyond the boundaries of b!. Suspiciously enough the string of characters finishes with 'a''b''c''\0'. Let's check address of a[0]:
(gdb) p &a[0]
$9 = 0x7fffffffdfe4 "abc"
See? The a field pointed by b is contiguous to a. Now you are making two mistakes here:
You are not properly initializing b.
b reserves 2 slots of memory. If you want to check palindromes of a fixed size of 3 characters you should reserve 4 slots like you did for the null terminated string "abc".
Try changing b declaration from:
char b[2];
To:
char b[] = "xyz";
Your initialization code will set the palindrome as a function of a, so it would do what you intend to.

Don't understand why while(*ptr++) enter while loop for 0 value (string terminator)

I have a problem with the following apperently trivial sample code:
(on visual studio 2015)
Please ignore the part with pointing to a literal constant, possible warnings or erros on the newwer compiler, that is not what I don't understand.
My problem is why it prints '0' and how the while loop works, tried using both debugger and printf. My understanding of the problem is this:
moves ptr to point at 'e'
checks content of ptr which is 'e' it is not 0 so it enters while loop
back to condition line, moves ptr to 'l'
checks *ptr, it is not 0, enters...
blah blah for the letters l, o
Then it increases ptr after 'o' and gets '\0', at which point by my logic it should NOT enter the loop, but i does, and no longer enters after one more step when it is pointing over the terminator at junk?!?
I looked over 2 other topics, this topic about operator precedence and this one about the while(*ptr) case going over the terminator, but I don't understand from the second WHY it enters the loop and thy it increases the pointer value afterwards? for what i understand the order is first increase pointer, then get the value with *
#include <cstdio>
#include<stdlib.h>
int main(void) {
char* str = "hello";
char* ptr = str;
char least = 127;
while (*ptr++) {
printf("%c-", *ptr);
least = ((*ptr) < (least)) ? (*ptr) : (least);
}
printf("%d\n", least);
}
Inside the loop you're not using the same character that you tested in the while condition.
Since ptr++ is a post-increment, it returns the current value of ptr and then increments it. So when ptr points to the o character, and you do
while (*ptr++)
it tests 'o', which is not zero, so it will enter the loop. But after the test it increments ptr to point to the next character, so now it points to '\0'. Then it prints this character and sets least to it.
You should increment the pointer after processing it. You can do this by moving ptr++ to the end of the loop body. Or you can use a for loop instead of while:
for (ptr = str; *ptr; ptr++)
The last printf call outputs the terminating zero of the string literal as an integer.
To make it clear consider a string literal with one actual character as for example "A".
Before the first iteration of the while loop
while (*ptr++)
{
printf("%c-", *ptr);
least = ((*ptr) < (least)) ? (*ptr) : (least);
}
the pointer ptr points to the character 'A' of the string literal. This expression
*ptr++
can be imagined like
char c = *ptr;
++ptr;
So the control passes to the body of the loop because 'A' is not equal to zero. Meantime the pointer ptr was increased after evaluation the condition. So now it points to the terminating zero '\0' of the string literal.
As 0 is less than 123 then the variable least gets the value 0.
least = ((*ptr) < (least)) ? (*ptr) : (least);
In the next iteration of the loop ptr still points to the terminating zero. So the control bypasses the body of the loop and the zero is outputted in the next statement after the loop.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).

Differences in strings

I am stuck on why *("Harry" + 2 ) and "Harry"[3] have the same output (r) but "Harry" + 1 output is (arry). What are the differences?
cout << "Harry" + 1 << endl;
cout << *("Harry" + 2 ) << endl;
cout << "Harry"[3] << endl;
cout << endl;
"Harry" + 1 points to one character after H, so now the string "lost" a character, H.
*("Harry" + 2) points to 2 characters after H, and so it points to the first r. Dereferencing it just the single character, which is r.
"Harry"[3] gets the third character in "Harry", which is the second r. Note that it is syntactic sugar to *("Harry" + 3).
"Harry" is a string of type const char*. The +1 operation gets the address that is one after the beginning address of "Harry", which is the address of the letter a. When printed as a string, starting from the second letter, you get "arry". Similarly, "Harry"+2 gets the address of the first r letter, so you get r when you dereference using *. The "Harry"[3] is equivalent to *("Harry"+3), so you should get the second r letter, which is still r.
In summary, you print a single letter if you dereference using *, but you print a string starting from an address of type const char* if you don't dereference.
Those integers in the first two lines are offset
cout << "Harry" + 1 << endl;
In this case, we have 1 byte offset: arry so it's gonna print arry
cout << *("Harry" + 2 ) << endl;
In this case, we have two bytes offset: rry and dereferencing it will print r
cout << "Harry"[3] << endl;
In this case it's just indexing Harry so it will print r which is the 4th element
Let's start with what you created with "Harry".
By definition what you created was a "const char[6]".
That is -- an array of 5 characters, terminated with a null character ('/0').
If you understand this fundamental, then the explanation provided by Rakete should make more sense, again assuming you understand how arrays and pointers work in c++, and the associated syntax of your examples.
Remember! Arrays are zero based. So when you specify var[3] you are asking for the 4th element. var[0] would be in this case the first element.
When you are using the stream operators with cout, you are manipulating the starting point of the string, that would typically be var[0].
In C/C++, a one-dimensional array can be decayed to a pointer to the first element. So when you write my_array + 2, what you are getting is the address of the third element in the array. Hence when you write *(my_array + 2), you get the value, which is equivalent to writing my_array[2].
Hence the output of "*(Harry + 2)" and "Harry[3]" is the same (Note: They both are indexing different elements, just that they both are 'r').
When you write "Harry + 1", you are passing the address of the second element to cout. cout treats this as a start of string and prints till the end and hence you get the out as "arry"

simple recursion tracing understanding stacks

I'm working on a fairly easy tracing exercise however I'm not completely understanding why the solution is what it is...
void f( int n) {
if (n>0) {
f(n-1)
cout << n << " ";
}
}
int main () {
f(5);
return 0;
}
the answer is 1 2 3 4 5, however I'm wondering how this is so, since everytime the function f is called it never gets to the cout line...I understand that there is a stacking system where the last function implemented is looked at, however until the factorial example where it returned a value to multiply to the previous n, I'm not understanding how this is similar. Please don't use the factorial example again, I do understand it, but I'm not udnerstanding how the cout is implemented here.. thank you for your help.
Consider the simple case of calling f(1). We pass the if test and make a recursive call to f(0). This call will return doing nothing and continue executing the body of f(1). The next statement is the call to std::cout << 1 << " ";:
// Substitute the parameter with the passed in argument n = 1
void f(1) {
if (1 > 0) {
f(0);
std::cout << 1 << " ";
}
}
You should now be able to handle the case of f(2), and in general f(n). Whenever you are stuck thinking about recursive programs, consider the base cases and then generalize. Write the code out by substituting the function parameters with actual arguments.
It does get to the output line, after the recursive call to f returns.
The important part here is the stopping condition:
if (n>0)
This makes the recursive call only happen if n is larger than zero. And as the recursive call is with the argument n - 1 it will be lower and lower until it's zero and no more calls will be made.
Lets trace it for you, since you are to lazy to do it yourself in a debugger (or on paper):
The first call from main is made. n == 5 and clearly larger than zero, so a recursive call is made with 5 - 1
In the second call, n == 4, still larger than zero so a call is made again with 4 - 1
In the third call, n == 3, still larger than zero so a call is made again with 3 - 1
In the fourth call, n == 2, still larger than zero so a call is made again with 2 - 1
In the fifth call, n == 1, still larger than zero so a call is made again with 1 - 1
In the sixth call, n == 0, which is not larger than zero, so no more calls are made and the function returns.
Returns to n == 1, and so 1 is printed and then the function returns
Returns to n == 2, and so 2 is printed and then the function returns
Returns to n == 3, and so 3 is printed and then the function returns
Returns to n == 4, and so 4 is printed and then the function returns
Returns to n == 5, and so 5 is printed and then the function returns to the main function
That is, this is how it should have worked if it compiled. Now it won't even get this far since you will have compiler errors (with the code as shown in your question).