|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2003-09-16 18:41 UTC] Jared dot Williams1 at ntlworld dot com
Description:
------------
Switched expressions seem to be cast to a type before case matching occurs.
If all case expressions are of the same type, either numeric, or string, this problem does not arise.
It is not clear why, or really what type the switched expression is cast to before comparision.
Reproduce code:
---------------
$t = array(0,1,2,3,'*','+','a', 'b')
foreach($t as $v)
switch ($v)
{
case 0: echo('0'); break;
case 1: echo('1'); break;
case 2: echo('2'); break;
case 3: echo('3'); break;
case '*': echo('*'); break;
default: echo($v); break;
}
Expected result:
----------------
0123*+ab
The first 5 array elements are output their respective case statements, and the latter 3 are handled by the default case.
Actual result:
--------------
01230000
The first 5 array elements are output their respective case statements, and the latter 3 are handled the 0 case.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 20:00:01 2025 UTC |
To add to the above, it seems that the '0' case is the culprit. If you use the code below where '10' replaces '0', the weird behavior does not occur: $t = array(10,1,2,3,'*','+','a', 'b'); foreach($t as $v) switch ($v) { case 10: echo('0'); break; case 1: echo('1'); break; case 2: echo('2'); break; case 3: echo('3'); break; case '*': echo('*'); break; default: echo($v); break; } OutPut: 0123*+ab So it seems that Case 0: grabs all the cases which are of a different data type if the case expressions are not of the same type i.e. numeric and string.The non-numeric string values are getting cast to integer value 0, which then match case 0:. $t = array(10,1,2,3,'*','+','3a', 'b'); foreach($t as $v) switch ($v) { case 10: echo('0'); break; case 1: echo('1'); break; case 2: echo('2'); break; case 3: echo('3'); break; case '*': echo('*'); break; default: echo($v); break; } Outputs: 0123*+3b as 3a gets cast to 3. so seems there is a missing a condition in the code somewhere, to see if the switched expression can actually be a numeric type. Also $t = array(10,1,2,3,'*','+','3a', 'b'); foreach($t as $v) switch ($v) { case 10: echo('0'); break; case 1: echo('1'); break; case 2: echo('2'); break; case '*': echo('*'); break; case '3a': echo('!!'); break; default: echo($v); break; } ?> Outputs: 012!!*+!!b So the case labels are getting cast too without the check.Oh erm, seems its not limited to switch either. :/ echo('a' == 0 ? 'YES' : 'NO'); Outputs: YES echo('3a' == 3 ? 'YES' : 'NO'); Outputs: YES echo(4 == '4a' ? 'YES' : 'NO'); Outputs: YES Surely these cant be considered equivalent.How's this for an impossibility.. echo('a' != 0 ? 'TRUE' : 'FALSE'); echo('<br />'); echo('a' ? 'TRUE' : 'FALSE'); Outputs: FALSE TRUEI do understand that time has fixed this "feature". As for explicit casting, it does result in different behaviour, when comparing string/values. $x = '0xF'; $y = (int)$x; echo($x == 15 ? 'YES' : 'NO'); echo('<br />'); echo($y == 15 ? 'YES' : 'NO'); Outputs: YES NO Strict equivalence testing doesnt help when you wish "1234" and 1234 to be considered equal.