Why does "- --" and "+ ++" and operate differently? - c++

Decrementation / Incrementation is a basic operation but it's precendence on - -- and + ++ confused me. I'll use decrementation for illustration:
I have a set here of different styles of operating between a and b: See it working here
#include <iostream>
using namespace std;
int a=10, b=7;
int main() {
// - and -- opearator // Results: Details:
a = 10, b = 7; cout << a---b << endl; // 3 a post-decrement
a = 10, b = 7; cout << a ---b << endl; // 3 a post-decrement
a = 10, b = 7; cout << a- --b << endl; // 4 b pre-decrement
a = 10, b = 7; cout << a-- -b << endl; // 3 a post-decrement
a = 10, b = 7; cout << a--- b << endl; // 3 a post-decrement
return 0;
}
I understand that the 4 output came from the decremented b which is 7 that turned to 6 and is subtracted from a which is 10.
Also, because of the other four statements, I thought the compiler treats all of them as --- but behold, here comes the confusion of - -- results. See it working here

Parsing follows the maximal munch rule, so all statements minus the third are interpreted as (a--)-b which decrements a and returns its previous value (which was 10).
The third one is a-(--b) which is a pre-decrement on b, so the new decremented value is returned.

I think this is because of the Maximal Munch Rule. From Wiki:
In computer programming and computer science, "maximal munch" or
"longest match" is the principle that when creating some construct, as
much of the available input as possible should be consumed.
From Expert C Programming:
The ANSI standard specifies a convention that has come to be known as
the maximal munch strategy. Maximal munch says that if there's more
than one possibility for the next token, the compiler will prefer to
bite off the one involving the longest sequence of characters.

But why didn't it decremented after it's statement?
Because the --X operator:
first performs the decrement
then returns the result of decrementing
So, there's no way that --b will 'decrement afterwards'. It always does it "before".
Confusion
Look carefully at code and results: Everytime where --- is written without spaces, the result is the same: three. Three is also the result for -- - case. Even with a pure guess, you could say that compiler parses it as -- -. In fact, it actually does it like that, because the C++ Standard requires it to do so. See comments about 'maximum munch' rule. Same follows for other multi-character operators, like ++.
In the other case where you have split that into - --, the compiler had no other option: it had to treat it literally as - -- because of the space in the middle. Just as -- -, this case is obvious and it's perfectly visible which part forms the -- operator and the compiler must obey that.

That statement is equivalent to 10-6 = 4,
rest are equivalent to 9-7 = 3.
#include <iostream>
using namespace std;
int a=10, b=7;
int main() {
// - and -- opearator // Results: Details after a statement:
cout << (a--)-b << endl; a=10, b=7; // 3 Both a and b decremented
cout << (a --)-b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a- (--b) << endl; a=10, b=7; // 4 Neither a or b decremented
cout << (a--) -b << endl; a=10, b=7; // 3 Both a and b decremented
cout << (a--)- b << endl; a=10, b=7; // 3 Both a and b decremented
return 0;
}

In this series of statements
cout << a---b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a ---b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a- --b << endl; a=10, b=7; // 4 Neither a or b decremented
cout << a-- -b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a--- b << endl; a=10, b=7; // 3 Both a and b decremented
you forgot to include one more statement:)
cout << a --- b << endl; a=10, b=7; // 3 Both a and b decremented
In all these statements
cout << a---b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a ---b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a--- b << endl; a=10, b=7; // 3 Both a and b decremented
cout << a --- b << endl; a=10, b=7; // 3 Both a and b decremented
The compiler parses outputed expression as
a-- -b
that is it tries to extract the longest valid token.
The value of the postdecrement operator as for example a-- is the value of its operand before decrementing. So in expression
a-- -b
the value of a-- is 10 and the value of b is 7. The difference is equal to 3.
And you have the only expression with the predecrement operator
cout << a- --b << endl; a=10, b=7; // 4 Neither a or b decremented
There the value of --b is the value of b after decrementing that is 6. So you have 10 - 6 that is equal to 4.
If you will substitute minus to plus in all these statements you will get the same effect
17
17
18
17
17
17 // this corresponds to my added statement a +++ b
So these operations - -- and + ++ behave in essense the same way.

Related

How do we properly use pointers and references to integers in a function (C++)?

I am having trouble understanding how to obtain the correct values outputted by the following C++ code when trying to solve it by hand.
#include <iostream>
using namespace std;
int f(int a, int & b,int *c){
a += 1;
b += 3;
*c += 4;
return a+b+(*c);
}
int main() {
int a = 3, b = 4,c = 5;
cout << "total: " << f(b,c,&a) << endl;
cout << "a= " << a << " b= " << b << " c= " << c << endl;
a = 3, b = 4,c = 5;
cout << "total: " << f(a,a,&a) << endl;
cout << "a= " << a << " b= " << b << " c= " << c << endl;
return 0;
}
I know the result should be:
total: 20
a= 7 b= 4 c= 8
total: 24
a= 10 b= 4 c= 5
But everytime I try to solve this code by hand (attempt to write out the steps and assignments on a piece of paper) I can't seem obtain the correct total or values. Can anyone help me understand what is happening inside the function with a, b, and c (maybe a step-by-step explanation?). There must be something I am not understanding with the referencing/dereferencing or the pointers that is causing mistakes in my logic. Even ChatGPT is spitting out the incorrect answer after trying to execute the code...
For example if I try the first set of of inputs inside the function, here's what I understand:
int a = 4;
int &b = 5; //since c = 5
int *c = &a; //&a = 3
Then I start to execute the body of the function:
a += 1 now gives me a = 5;
b += 3 now gives me c = 8 since b is a reference to c so it really only is c that changes;
*c += 4 now takes the value stored in &a initialized as 3 and adds 4 so a's new value is 7;
The final tally is a = 7, b = 4 (hasn't changed), and c = 8. These values are correct, but the return portion of the function does not work with these values:
a+b+(*c) should be 7+4+(7), but the result of that is 18, while the correct answer is 20.
What's worst is that if I use the same logic for the second time the function is called, my values are incorrect but my total is correct... I'm lost.
The final tally is a = 7, b = 4 (hasn't changed), and c = 8.
These values are correct, but the return portion of the function does not
work with these values:
What is getting you tripped up is that a, b, and c in your main are not the same as a, b, and c in the f(). The
return a+b+(*c);
Uses what f() knows as a, b, and c. This is part of f(). f()'s variables is the only thing that this return statement knows anything about, and it has absolutely no knowledge at all, whatsoever, about any variables in main. So to know what these variables are you just have to reread what you wrote yourself:
a += 1 now gives me a = 5;
b += 3 now gives me c = 8 since b is a reference
but this b, right here is the very exact, same b that's in the return expression.
*c += 4 now takes the value stored in &a initialized as 3 and adds 4 so a's new value is 7;
But this is the c in the expression. So
return a+b+(*c);
computes 5+8+7 or 20, as you've observed.
The second expression works the same way.
You're getting tripped up by the fact that f()'s variables use the same names as the variables in main(). It also doesn't help that pointers and references from one refer to variables in the other.
It might be helpful for you to rename the variables in f():
int f(int x, int & y,int *z){
x += 1;
y += 3;
*z += 4;
return x+y+(*z);
}
This should be logically equivalent to the original function, but with less confusion.
This is easiest to do with pictures, so I'll try to make some ascii art that shows what is going on.
Here is the situation just after the first call has entered f:
main a:3 b:4 c:5
^ ^
| /---/
| /
f c:* b:* a:4
Here 'main' and 'f' each have their own 'a', 'b', and 'c'; and 'b' and 'c' in 'f' point at/refer to things in main's stack frame. I've reversed the order c/b/a in 'f' in order to not have crossing lines.
After the 3 adds in f, we have
main a:7 b:4 c:8
^ ^
| /---/
| /
f c:* b:* a:5
In the second call to f, things look like:
main a:3 b:4 c:5
^
|\--\
| \
f c:* b:* a:3
and after the adds:
main a:10 b:4 c:5
^
|\--\
| \
f c:* b:* a:4

How do ncrement and decrement operators work in C++ [duplicate]

This question already has answers here:
What is the difference between prefix and postfix operators?
(13 answers)
Closed 12 months ago.
The community reviewed whether to reopen this question 12 months ago and left it closed:
Original close reason(s) were not resolved
I was working with my practicals and my tutor taught us the increment and decrement operators but I cannot understand a few things in code. The code is as follows :
#include < iostream >
using namespace std;
int main() {
int a = 10 , b = 100 , result_a , result_b ;
// Prefix Example
// Printing the value given by increment Operator on A
result_a = ++a;
cout << "Prefix Increment A : " << result_a << endl;
// Printing the value given by decrement Operator on B
result_b = --b;
cout << "Prefix Decrement B : " << result_b << endl;
cout << a << endl << b << endl;
// Postfix Example
// Printing the value given by increment Operator on A
result_a = a++;
cout << "Postfix Increment A : " << result_a << endl;
// Printing the value given by decrement Operator on B
result_b = b--;
cout << "Postfix Decrement B : " << result_b << endl;
cout << a << endl << b << endl;
cout << result_a << endl << result_b;
system("pause>0");
return 0;
}
And the output is as follows :
PS D:\Burhan\My coding projects\C++\WalletTerminal> if ( $? ) { g++
main.cpp -o main } ; if ( $? ) { .\main }
Prefix Increment A : 11
Prefix Decrement B : 99
11
99
Postfix Increment A : 11
Postfix Decrement B : 99
12
98
11
99
I don't understand why is the Postfix Increment A: 11 and Postfix Decrement B: 99 as my calculations say that it should be 12 and 98 which are the value of A and B. We are actually adding +1 to A and B but as far as I know, that happens after the line of code is executed but still, it doesn't work as intended. Can you please tell me how that works? I look on the internet but couldn't find any issues related to this.
You can look at it this way, when you use pre-increment or pre-decrement (++a, --b ) , what really happens is that for instance here
result_a = ++a;
What really happens is,( since ++ is a short-hand operator for incrementing)
a=a+1;
result_a=a;
Similarly for post-increment or post-decrement (a++,b--)
result_b = b--;
what really happens is
result_b=b;
b=b-1;
++a (Prefix) means firstly incrementing a and then using the value of a. a++ (Postfix) means firstly using the value of a and then incrementing a.
For example:
int a = 10;
std::cout << a++; // Will print out 10
// a == 11
int a = 10;
std::cout << ++a; // Will print out 11
// a == 11

getting strange values for pointer and a regular int

I'm trying to learn about stack and heap at c++ and just started to print tests to learn how it's work.
I wrote this code:
`#include <iostream>
using namespace std;
int main (){
int a;
int b;
int *c;
int *c2;
int *d{new int};
cout << &a << " a= " << a << endl;
cout << &b << " b= " << b << endl;
cout << &c << " c= " << c << endl;
cout << &c2 << " c2= " << c2 << endl;
cout << &d << " d= " << d << endl;
delete d;
return 0;
}
the output is:
0x7ffefad88d00 a= 124
0x7ffefad88d04 b= 0
0x7ffefad88d08 c= 0
0x7ffefad88d10 c2= 0x400b20
0x7ffefad88d18 d= 0xec9c20
There are 3 things I do not understand:
why a value is 124?
why c value is 0 and not a pointer like c2 that have the same syntax?
why c size is just 2 byts and not 4?
a, b, c, d and the value of *d are uninitialized, reading them is undefined behavior. Anything can happen, nobody can predict the value of those variables. See this question for more information.
About the printout of the pointers, many implementations trim leading 0s. See this question. If I try to print out the values of pointers in Visual Studio 2015, I get the leading zeros.
why a value is 124?
a is uninitialized, hence reading it will give you unpredictable value. Reading uninitialized non-static local variable is UB. But, uninitialized global and static variables are initialized with 0 at compile time and reading them is fine.
why c value is 0 and not a pointer like c2 that have the same syntax?
c is also uninitialized, so what it points to is also undefined as mentioned above. It is a pointer like c2, but it points to NULL (which is 0).
why c size is just 2 bytes and not 4?
c size of a pointer is architecture and/or compiler dependent. In this case c occupied 8 bytes. subtract the address of c from the address of c2.
0x7ffefad88d10 - 0x7ffefad88d08 = 0x000000000008 these are hexadecimal values not decimal.
So, c is actually a pointer like c2 and occupies same space in the memory.

Swap two numbers without a third in C/C++ [duplicate]

This question already has answers here:
Swapping two variable value without using third variable
(31 answers)
Closed 6 years ago.
we usually use the
a=a+b;
b=a-b;
a=a-b;
logic to solve this code, however, if we work with int, then after say 30000 the code fails, if we take long, it fails after say 1000000 or so. My objective is, not to increase the length of the code yet, do the same operation. I have already tried using a BIT wise XOR,
a = a ^ b;
b = a ^ b;
a = a ^ b;
Still it didn't help, any ideas?
To swap a variable a and a variable b: std::swap(a, b);
Example:
int a = 10;
int b = 20;
std::cout << "Before swap\n";
std::cout << "Value of a: " << a << '\n';
std::cout << "Value of b: " << b << '\n';
std::swap(a, b);
std::cout << "After swap\n";
std::cout << "Value of a: " << a << '\n';
std::cout << "Value of b: " << b << '\n';
Output using GCC 4.9.2:
Before swap
Value of a: 10
Value of b: 20
After swap
Value of a: 20
Value of b: 10
This way of doing it uses rvalues internally, so it has next to zero overhead for other use cases and won't overflow for any primitive type ever

Why does this C++ code output the result?

This is the C++ code:
#include<iostream>
using namespace std;
int a=8;
int fun(int &a)
{
a=a*a;
return a;
}
int main()
{
cout << a << endl \
<< fun(a) << endl \
<< a << endl;
return 0;
}
why does it output:
64 64 8
the << operator's associativity is left to right, so why not output 8 64 64?
Does it have the relation to the sequence point and the effect side?
Associativity and evaluation order are not the same thing. The expression a << b << c is equivalent to (a << b) << c due to left-to-right associativity, but when it comes to evaluation order, the compiler is free to evaluate c first then a << b and, likewise, it can evaluate b before it evaluates a. In fact, it can even evaluate the terms in the order b → c → a if it wants, and it just might if it concludes that such an order will maximise performance by minimising pipeline stalls, cache misses, etc.