Explain how it happens exactly internally in the PHP script interpreter (in windows or php.exe
), PHP is written in c, the code is this:
Code:
PHP_FUNCTION(chr)
{
zend_long c;
if (ZEND_NUM_ARGS() != 1) {
WRONG_PARAM_COUNT;
}
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1)
Z_PARAM_LONG(c)
ZEND_PARSE_PARAMETERS_END_EX(c = 0);
c &= 0xff;
ZVAL_INTERNED_STR(return_value, ZSTR_CHAR(c));
}
The responsible line is this:
c &= 0xff;
This notation 0x
that is in front of the ff
means hexadecimal (base 16), its calculation is made so:
- each
f
worth 15, then 16 to 1 is 16 even
- getting
15 * 16
- 16 to 0 is 1
- getting
15 * 1
- sum both
The calculation:
15 * 16^1 + 15 * 16^0 = 255
(15 * 16) + (15 * 1) = 255
The final value is 255
Important note: with the exception of zero itself, any zero value will result in 1, for example:
- 30 = 1
- 100 = 1
- 220 = 1
- 20180 = 1
Zero cannot be determined:
So why convention programming is considered to be equal to 1 (00 = 1), an example in PHP can thus be tested with the function pow(base, expoente)
:
var_dump(pow(16, 0));
var_dump(pow(0, 0));
Or in PHP 5.6+:
var_dump(16 ** 0);
var_dump(0 ** 0);
Example https://ideone.com/QAx9Dh
Just to better explain the base 16 formula, if this were it 0xff00
would be so:
15 * 16^3 + 15 * 16^2 = 65280
Operation:
(15 * 256) + (15 * 4096) = 65280
3840 + 61440 = 65280
The value 65280
- then the rightmost value is always raised to zero
- the second most right raised to a
- the third from right to left is raised to two
And so on, as in the second example we had two zeros after the ff
(which results in zero in the calculation and therefore disregarded in the formula), then one of them was raised to 2 and the other to three.
Returning the formula, in the result of the execution of the programme (from the function PHP_FUNCTION(chr)
) we’ll have this:
c &= 255;
The operator &=
amounts to this c = c & 255;
, this operator &
(or &=
) is an operator bitwise called AND
(not to confuse with &&
, although similar) for binary logic, so in an operation it will compare bit by bit and will return a 1 whenever both when compared are 1, has a response on the website about this:
So 255 equals 011111111
and the amount you put 300 would equal 0100101100
, as 255 bits is smaller then a zero is added to your left (even if it was the other way around 255 & 300
):
255: 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1
300: 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0
------------------------------------------------
Resultado: 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0
Then we’ll have 0000101100
that converted results in 44
Note: to facilitate understanding the operations one can remove the zeros to the left, thus:
255: 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1
300: 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0
---------------------------------------------
Resultado: 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0
The converted value will be the same at the end.
These operations can be done in several programming languages (I don’t know if you have one that doesn’t support), so you can test in Javascript:
var valor = prompt('Insira o numero');
var range = 255;
valor = parseInt(valor);
if (valor) {
var x = valor & range;
alert(x);
} else {
alert('Numero inválido');
}
An example in PHP would be:
<?php
$valor = 44;
$range = 255;
$x = $valor & $range;
var_dump($x);
Dude, I reviewed the PHP repository behind this excerpt... Very good!
– Woss
Perfect! Thank you very much, now it’s super clear.
– Leonardo