ST3
ST3

Reputation: 8946

a = (a + b) - (b = a); C++ vs php

I've been looking around and found formula: a = (a + b) - (b = a) it is supposed to swap two variables (or objects in some cases). However I tested it with C++ and php, these gave me different result.

php:

$a = 10;
$b = 20;
$a = ($a + $b) - ($b = $a);
echo $a, " ", $b;

This prints 20 10

C++

int a = 10;
int b = 20;
a = (a + b) - (b = a);
std::cout << a << " " << b;

This prints 10 10

Code looks the same but outputs are different, I've been thinking about two reasons:

  1. C++ code is compiling and php is interpreting.
  2. This formula is useless because it leads to undefined behavior.

Can somebody explains, why C++ and php output differs in this situation?

Upvotes: 5

Views: 866

Answers (3)

MAnyKey
MAnyKey

Reputation: 567

C++ code is completely broken because of undefined behavior. (read and write b in one sequence point).

Upvotes: 3

user1646111
user1646111

Reputation:

For PHP:

$a = 10;
$b = 20;
$a = ($a + $b) - ($b = $a);
//executes like thus
$a = (30) - ($b = $a);
$a = (30) - ($b = $a = 10); //new $a still not computed, using older $a
$a = (30) - (10);
$a = 20;
//then, $a=20 and $b = 10

This is totally related to Operator Precedence, this might be same in C or might not, it depends on precedence if unexpected behavior not occur.

Upvotes: 2

Mats Petersson
Mats Petersson

Reputation: 129524

I'm not sure what the rules are in PHP, but in C++, the order of individual sub-expressions isn't strictly defined, or as the technical term is, it is "unspecified" - in other words, the compiler is allowed to calculate b = a before or after it does a + b. As long as it does a + b and b = a before the subtraction. The use of "unspecified" behaviour allows the compiler to produce more efficient code in some cases, or simply that it's possible to build a compiler for some architectures.

It also means that if you have an expression that "recalculates" a value within the expression itself, and also using it elsewhere in the expression, you get unedefined behaviour (UB for short). UB means just that, the behaviour is not defined - almost anything could happen, including what you are seeing and many other alternatives (e.g. the compiler is allowed to produce 42 as a result as well, even if logic says the answer wouldn't be 42 in this case [it's the wrong question for that!]).

I would also suggest that if you want to swap two values, in PHP:

 $t = $a;
 $a = $b;
 $b = $t;

and in C++:

 #include <algorithm>

 std::swap(a, b); 

or if you insist on writing your own:

 int t = a;
 a = b;
 b = t; 

Trying to be clever and perform it "without temporary variable" is almost certainly going to make it slower than the use of a temporary - certainly in a compile language like C++ - in a interpreted language like PHP, creating a new variable may add a bit of extra overhead, but it's unlikely to be that big, compared to the extra effort in the logic required.

Upvotes: 14

Related Questions