Почему var_dump('0xafebac' == '11529132');
равно TRUE? Как происходит сравнение этих двух строк?
Это довольно длинная история.
РНР - язык со свободной типизацией. В нем можно спокойно сравнивать переменные любых типов, использовать их в различных выражениях и операторах. Например, для РНР нет проблемы вычислить. сколько будет 2 * '2'
- он просто приведёт оба операнда к числовому типу, и выполнит операцию умножения.
Но за такую легкость приходится платить. В частности, РНР должен догадаться, что в переменной содержится число, даже если она имеет тип "строка". Почему так? А потому, что в большинстве случаев все переменные, попадающие в РНР извне, имеют тип "строка". Например, это все переменные, попадающие в скрипт по протоколу НТТР. Или переменные, попадающие в скрипт из базы данных через устаревшие протоколы.
И если мы хотим сравнить переменную, полученную из формы с переменной, полученной из БД, то нам в обязательном порядке надо попытаться привести их к числам, а иначе у нас будет '9' больше чем '100'. Вот РНР и пытается "догадаться" - является ли переменная числом, и если да - то приводит её к числовому типу.
Чтобы этого не происходило, надо сравнивать строки либо оператором строгого сравнения, ===
, либо функцией strcmp()
.
При этом выражение вида '0xafebac' == '11529132'
является частным случаем, который был
исправлен в версии 7.0: начиная с этой версии, строки, которые выглядят, как шестнадцатеричные, перестали распознаваться, как числовые.
Но при этом строки, которые выглядят, как число с экспонентой (например '1e3') всё еще распознаются как числа и поба операнда приводятся к числу. Поэтому '1e3' == 1000
будет true
Потому что в php при сравнении приводит обе строки к числу. Даже если оба операнда это строки. По факту это баг. В версиях выше 5.6 поведение стало более предсказуемым:
При нестрогом сравнении строки с числом, строка преобразуется к числу по описанным в документации правилам. А так как 'text' - это не числовая строка, то она преобразуется к 0.
Вот так устроено нестрогое сравнение в PHP.
ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
...
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG): ...
case TYPE_PAIR(IS_DOUBLE, IS_LONG): ...
case TYPE_PAIR(IS_LONG, IS_DOUBLE): ...
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): ...
case TYPE_PAIR(IS_ARRAY, IS_ARRAY): ...
case TYPE_PAIR(IS_NULL, IS_NULL):
case TYPE_PAIR(IS_NULL, IS_FALSE):
case TYPE_PAIR(IS_FALSE, IS_NULL):
case TYPE_PAIR(IS_FALSE, IS_FALSE):
case TYPE_PAIR(IS_TRUE, IS_TRUE):
...
case TYPE_PAIR(IS_NULL, IS_TRUE): ...
case TYPE_PAIR(IS_TRUE, IS_NULL): ...
case TYPE_PAIR(IS_STRING, IS_STRING): ...
case TYPE_PAIR(IS_NULL, IS_STRING): ...
case TYPE_PAIR(IS_STRING, IS_NULL): ...
case TYPE_PAIR(IS_OBJECT, IS_NULL): ...
case TYPE_PAIR(IS_NULL, IS_OBJECT): ...
default:
...
if (Z_TYPE_P(op2) == IS_OBJECT) {
...
if (!converted) {
...
} else {
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 1);
op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 1);
...
converted = 1;
}
...
Если не найдена необходимая пара типов, то оба операнда преобразуются к числу и идут на следующую итерацию while
Собственно из-за приведения типов при нестрогом сравнении и получаются вот такие паззлеры:
'text' == 0; // true
false == 0; //true
'text' == false; // Внезапно false
Потому что сравнения для строк через ==
не реализовано. PHP видит что строки содержат числа и приводит их числу перед проверкой.
Для сравнения строк лучше использовать strcmp так её поведение не зависит от типа данных.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Проверив код программы увидел, что lcg_value() генерирует такие точки, что укладывает их по сути все рядомЗначение сильно не меняется
Подскажите, почему file_put_contents в моем коде ниже, записывает не все содержимое, как исправить?
Только начал изучать php вопрос может прозвучать не совсем корректно для более опытных
Как реализовать галерею изображений одного товара в каталоге? Нужна реализация на php mysqlНе могу найти решение подобного вопроса