Что такое null и как с этим жить: сравнение с null в PHP, тонкости в приведении типов данных. Значение слова null

В работе с любыми данными то и дело требуется как-то обозначить их отсутствие. Новички зачастую для этой цели используют значение false , которое, по сути, является не отсутствием данных, а определённым значением типа boolean . Для того, чтобы как-то помечать неопределённость или отсутствие данных , существует специальное значение null . Про false , null и прочее уже немало сказано и добавить что-то оригинальное крайне сложно. Но гораздо сложнее бывает найти баг, вызванный неочевидным поведением этих штуковин. Поэтому, вдохновлённый одним таким багом, самым элегантным в моём послужном списке, я решил написать маленькую шпаргалку на эту тему.

Перегружать пост интересными, но довольно-таки бесполезными я не стану. Вместо этого перейду сразу к делу и приведу цитату со , посвящённой null:

Специальное значение NULL представляет собой переменную без значения. NULL - это единственно возможное значение типа null. Переменная считается null, если:

  • ей была присвоена константа NULL.
  • ей еще не было присвоено никакого значения.
  • она была удалена с помощью unset().

До этого момента всё кажется простым, но чтобы так оставалось и дальше, при работе с null нужно придерживаться определённых правил.

Математические операции с null

Во всех математических операциях null ведёт себя аналогично int(0):

$a = null; $a + 1; // int(1) $a - 1; // int(-1) $a * 1; // int(0) 1 / $a; // bool(false)

Проверка переменной на null

Чтобы точно узнать, что переменная содержит null (то есть, ничего не содержит), нужно использовать либо специальную функцию is_null() либо тождественное сравнение === , а любые другие способы не подойдут:

// Правильная проверка переменной на null $a = null; is_null($a); // bool(true) $a === null; // bool(true)

Проверка null if-выражениях, а так же в функциях empty() и isset()

Тут переменные с null ведут себя абсолютно предсказуемо, как и любые другие ложные значения (которые в if-выражениях приводятся к false ). Но нужно помнить, что это не гарантирует нам, что в переменной находится именно null:

// В if-выражениях null приводится к false, как и все другие ложные значения if($a) { echo "Sure, $a is not null!"; } else { echo "Mabye $a is null." } // Проверка на empty() вернёт true, но не гарантирует, что проверяемая переменная - именно null $a = null; empty($a); // bool(true) $a = ; empty($a); // bool(true) $a = ""; empty($a); // bool(true) $a = 0; empty($a); // bool(true) $a = false; empty($a); // bool(true) // Проверка isset() вернёт false не только для null, но для не определённой переменной $a = null; isset($a); // bool(false) isset($undefined); // bool(false)

Сравнение двух null

В PHP как гибкое, так и тождественное сравнение двух null всегда возвращает false , в отличие от многих других платформ, где сравнение двух неизвестностей возвращает так же неизвестность (то есть, null ).

// PHP уверен, что две неизвестности равны, и даже тождественно равны $a = null; $b = null; $a == $b; // bool(true) $a === $b; // bool(true)

Поведение null при нетождественном сравнении с приведением типов данных

PHP разрешает сравнивать null -ы не только между собой, но и с другими типами данных. При этом не стоит забывать, что гибкое сравнение в php не является транзитивным, то есть, если два значения равны третьему по отдельности, не гарантирует их равенство между собой. Согласно , гибкое сравнение null при помощи оператора == с разными значениями возвращает разные результаты:

// Для всех ложных значений гибкое сравнение с null возвращает true, кроме строки "0" $a = ; $a == null; // bool(true) $a = ""; $a == null; // bool(true) $a = 0; $a == null; // bool(true) $a = false; $a == null; // bool(true) // А при сравнении null со строкой "0" мы получим false, хотя null == false и "0" == false $a = "0"; $a == null; // bool(false) // Для всех неложных значений такое сравнение так же вернёт false $a = 1; $a == null; // bool(false) $a = "1"; $a == null; // bool(false)

Сравнение с null с помощью >, =,

Не мне судить, насколько это является очевидным, но при сравнении с числами null всегда оказывается меньше них . Смотрите сами:

// Не смотря на то, что null == 0, он оказывается меньше любого числа null = -1) // bool(true) null >= 0 // bool(true) !(null >= 1) // bool(true)

На вид ничего особенного, но из этого следует, что если в дело вмешивается null, может пройти бессмысленная, на первый взгляд, проверка:

// Из-за подобного поведения я словил однажды баг, из-за которого почти поверил в магию:) $a = null; if($a = 0) { echo "$a = 0 at the same time!"; }

Разное поведение null в PHP, SQL и JavaScript

А вот это, на мой взгляд, самое скверное. Реализуя логику работы с ячейками баз данных, в которых разрешено значение null , на разных этапах продвижения данных от сервера к пользователю (например, MySQL -> PHP -> JavaScript ) поведение null может меняться.

Исследование null в JavaScript (а вместе с ним и загадочного undefined ) заслуживает отдельной статьи. Главное отличие состоит в том, что, не смотря на приведение типов, null в JavaScript ничему не равен, кроме самого null и этого самого undefined , хотя в if-выражениях и срабатывает аналогично false . А при сравнении с числами он выдаёт ещё более забавные результаты, чем в PHP.

NULL в MySQL , к примеру, действует гораздо более прямолинейно. Он просто при любых действиях с null (даже при сравнении двух null ) возвращает null . С его точки зрения, при любых действиях с неизвестностью в результате получится какая-то другая неизвестность:)

Простое правило при работе null, которое помогает избегать проблем

Вообще-то, не стоило читать этот пост. Держать в голове все эти нюансы, которые разные платформы трактуют по-разному, - неблагодарное занятие. Для того, чтобы избежать проблем с null нужно запомнить всего лишь одно правило:

Старайтесь не выполнять с null никаких лишних действий: не нужно его ни с чем сравнивать, складывать, сортировать. Там, где чисто теоретически переменная с null может просочиться в какие-то операторы, лучшим решением будет сперва проверить её функцией is_null(). 08.04.2014

"ВКонтакте" - это на сегодняшний день самый удобный русскоязычный ресурс, который является не только популярнейшей социальной сетью, но и сервисом для прослушивания аудиозаписей и просмотра видео. Здесь собрана огромнейшая библиотека музыкальных композиций, аудиокниг, клипов, фильмов и прочего добра. Естественно, что все зарегистрированные участники с удовольствием пользуются предоставленными им возможностями. Однако в последнее время все чаще стали появляться жалобы по поводу "шуточек", которые выкидывает система. Все они сводятся к ошибке JavaScript Error "ВКонтакте", которая мешает нормальной работе видео и аудио-проигрывателей.

Типы ошибок JavaScript Error: краткий обзор

Эта незадача может существенно подпортить настроение тем, кто предвкушал насладиться приятной музыкой или скоротать время за вечерним кинопросмотром. Чтобы такого не допустить, давайте разберемся, как исправить JavaScript Error "ВКонтакте" собственными силами. Есть несколько возможных вариантов решения проблемы.

Для начала посмотрим, какого типа ошибки могут появиться:

  • initAddMedia is not defined;
  • cannot read property "length" of undefined;
  • cannot convert "opts.photos" to object;
  • cannot read property parentNode;
  • currentaudioid либо просто undefined.

Это отнюдь не весь перечень возможных сообщений об ошибке, но здесь перечислены наиболее часто встречающиеся варианты. Далее рассмотрим существующие способы их решения.

Способы борьбы с ошибками JavaScript

Если при попытке включить аудио или открыть видеофайл у вас ничего не получается, а в верхнем углу экрана появляется ненавистное сообщение о том, что произошла ошибка JavaScript Error "ВКонтакте", то попробуйте для начала сделать следующее:

  1. Воспользоваться другим браузером. Например, если на данный момент вы работаете в "Опере", то установите "Гугл Хром" или "Мазилу". Возможно, проблема исчезнет.
  2. Нажать на клавиатуре сочетание клавиш Ctrl+F5. В некоторых случаях это действие убирает ошибку.
  3. Проверить компьютер с помощью антивируса (Dr.Web или другого). Не забудьте предварительно обновить программу.
  4. Откройте меню "Мои настройки" со своей страницы "ВКонтакте" и установите галочку напротив пункта "Всегда использовать безопасное соединение". Возможно, это тоже поможет.
  5. Почистите кэши используемых браузеров, очистите кэш Java.

Если ни одно из этих действий не помогло и ошибка "ВКонтакте" JavaScript Error все еще не дает вам пользоваться всеми функциями ресурса, то следующий способ решения проблемы должен сработать.

Обнаружение и удаление вируса в системном файле hosts

Вероятно, причиной такого неприятного инцидента являются вирусы, закравшиеся в вашу компьютерную систему. Они работают хитро: делают записи в системном в результате чего блокируется доступ к некоторым сайтам (отсюда и ошибка JavaScript Error "ВКонтакте" при попытке воспользоваться данным сервисом). Следовательно, для того чтобы открыть доступ, нужно почистить соответствующий файл, то есть hosts. Сделать это можно в автоматическоим либо ручном режиме. Мы рассмотрим, как это сделать самостоятельно.

Инструкция по чистке файла "хостс"

  1. Заходим в "Мой компьютер" и открываем системную папку Widows/system32. В ней имеется папка драйверов drivers, в которой нам нужна та, что называется etc. Среди файлов, хранящихся в этой последней папке, будет нужный нам hosts. Открываем его с помощью программы "Блокнот" либо текстового редактора WordPad.
  2. Вы увидите содержимое этого файла в виде текстовой записи. При этом в исправном (незараженном вирусом) файле запись ограничивается следующими данными: 127.0.0.1.localhost.
  3. Если вы обнаружили, что помимо указанного текста в файле имеются и другие записи, то это не что иное, как мусор, оставленный хитроумным вирусом. Именно он не дает программам на сайте "ВКонтакте" нормально работать, блокируя доступ к ним.
  4. Нам нужно избавиться от лишних записей. Полностью очищаем документ (в целях лучшей безопасности), а нужное сообщение вводим заново. Сохраняем изменения и закрываем редактор.
  5. Теперь нужно перезагрузить компьютер, после чего ошибка должна исчезнуть. Попробуйте зайти на свою страничку в соцсети и прослушать аудиофайлы, а также открыть видео. Ошибка JavaScript Error "ВКонтакте" больше не появляется.

Этот способ самый надежный, но в то же время достаточно простой. Как правило, он помогает решить проблемы, связанные с ошибками JavaScript. Чтобы не допустить подобных неприятностей, проверьте работу своего антивируса. При необходимости обновите его или установите новый, ведь надежная защита компьютера - основа бесперебойной работы, в том числе и при пользовании сайтами во всемирной сети.

Другие типы ошибок JavaScript "ВКонтакте"

Помимо проблем с аудио и видеофайлами, эта социальная сеть может "порадовать" и рядом других, еще более нелепых ошибок JavaScript Error "ВКонтакте". Что делать, если не открываются диалоги, не отправляются сообщения и не прикрепляются комментарии к фотографиям - выдается ошибка addEventListener; не работает стена - wall is not defined; отсутствует доступ к другим важнейшим функциям. Этот список - лишь часть косяков системы или сбоев, в результате которых затрудняется использование популярного ресурса.

Варианты решения проблем JavaScript Error

Независимо от того, какая конкретно ошибка JavaScript у вас возникает, способы ее решения сводятся к одним и тем же действиям. Как правило, достаточно воспользоваться одним из описанных выше вариантов. Особенно стоит обратить внимание на переустановку/смену используемого браузера и чистку файла "хостс".

Также можно попробовать сделать сброс установленных параметров браузера (вкладка "Свойства/Дополнительно"). После этого потребуется перезагрузить компьютер. В некоторых случаях это простое действие помогает избавиться от всплывающей ошибки. Кроме того, необходимо проверит на вирусы всю операционную систему, возможно, они притаились где-либо в другом месте. Для этого нужно иметь мощный и исправно работающий антивирус.

Последняя "инстанция"

Если же с вашей машиной и системой все в порядке, но при попытке воспользоваться какими-то функциями популярного ресурса все равно возникает ошибка JavaScript Error "ВКонтакте", как исправить ее в этом случае? Дело, скорее всего, в самом сервисе. Самым лучшим решением будет обратиться за помощью в техническую поддержку сайта "ВКонтакте" и объяснить возникшую ситуацию. Вероятно, там смогут разрешить это недоразумение.

Самый главный совет - предпримите все от вас зависящее, чтобы обеспечить полную безопасность своей компьютерной системы. Регулярно обновляйте антивирус, а также по возможности используйте самые последние версии браузеров. Тогда подобные ошибки будут сведены к минимуму.

Раздел очень прост в использовании. В предложенное поле достаточно ввести нужное слово, и мы вам выдадим список его значений. Хочется отметить, что наш сайт предоставляет данные из разных источников – энциклопедического, толкового, словообразовательного словарей. Также здесь можно познакомиться с примерами употребления введенного вами слова.

Найти

Значение слова null

Википедия

NULL (SQL)

NULL в Системах управления базами данных, которое может быть записано в поле таблицы базы данных. NULL соответствует понятию «пустое поле», то есть «поле, не содержащее никакого значения». Введено для того, чтобы различать в полях БД пустые значения (например, строку нулевой длины) и отсутствующие значения.

NULL означает отсутствие, неизвестность информации. Значение NULL не является значением в полном смысле слова: по определению оно означает отсутствие значения и не принадлежит ни одному типу данных. Поэтому NULL не равно ни логическому значению FALSE, ни пустой строке, ни нулю. При сравнении NULL с любым значением будет получен результат NULL, а не FALSE и не 0. Более того, NULL не равно NULL!

NULL (Си)

NULL в языках программирования Си и C++ - макрос , объявленный в заголовочном файле stddef.h . Константа нулевого указателя - это целочисленное константное выражение со значением 0, или такое же выражение, но приведённое к типу void *. Константа нулевого указателя, приведённая к любому типу указателей, является нулевым указателем . Гарантируется, что нулевой указатель не равен указателю на любой объект или функцию. Гарантируется, что любые два нулевых указателя равны между собой. Разыменовывание нулевого указателя является операцией с неопределённым поведением.

Иначе говоря, реализация предоставляет специальное значение - константу нулевого указателя, которую можно присвоить любому указателю и такой указатель при сравнении не будет равен любому «корректному» указателю. То есть, можно считать, что нулевой указатель не содержит корректный адрес в памяти.

NULL

  • NULL - нулевой указатель в языках программирования Си и C++.
  • NULL (SQL) - специальное значение, означающее, что значение поля не определено.

Когда я только начинал изучать программирование на языке C на первых курсах вуза, слово NULL , которое я однажды увидел в коде, приведённом лектором на доске, привело меня пусть и не в благоговейный, но, всё-таки, в трепет. Слово, вроде, похоже на "ноль", но на самом деле, наверно, не ноль. Для чего нужен этот вызывающе-угрожающий "капслок"? А имеет ли этот NULL какое-нибудь отношение к нулю? На эти вопросы, возникающие в моей голове, ответов не находилось.

А перед этим словом шло странное двойное равенство. Зачем же преподаватель дважды написал знак "равно"? Сначала я подумал, что, это, наверно, описка. Или же мел сплоховал в середине длинных чёрточек. Но в той же самой конструкции, которая содержала NULL и двойное равенство, было ещё и обычное равенство, и чёрточки в нём были совсем не длинные. И я начал смутно догадываться о том, что NULL - это какой-то необычный ноль, а два знака "равно" означают какое-то необычное равенство. Всё в этом новом и непонятном для меня языке программирования было необычно.

Эту строку, которая повергла меня в шок много лет назад, я приведу в данной статье. А сейчас мы попробуем разобраться с тем, что представляет собой NULL , как он используется и можно ли заменить его "обычным" нулём.

NULL - это макрос, определение которого содержится в библиотеке stdlib.h . Его значением является адрес, доступ к которому не предусмотрен. Программа, в которой используется макрос NULL , никогда не размещает никаких данных по этому адресу.

Значение NULL может быть присвоено указателю любого типа, в том числе, и нетипизированному. Например, все следующие присвоения корректны:

Char *p1 = NULL; int *p2 = NULL; void *p3 = NULL;

Указатель, содержащий значение NULL , называется нулевым . Таким образом, указатели p1 , p2 и p3 , описанные выше, – нулевые.

Давайте теперь рассмотрим ситуации, в которых используются макрос NULL и нулевые указатели.

    Функции динамического выделения памяти обычно обычно возвращают адрес выделенного участка в случае успеха, а в случае неудачи возвращают NULL . Именно таким образом ведёт себя, например, библиотечная функция malloc() . Благодаря этому, код, вызывающий такую функцию, может корректно обработать ситуацию, в которой память выделить не удалось; проиллюстрируем это следующим примером:

    Int *p; //Создаём указатель if ((p = malloc(100 * sizeof(int))) == NULL) //Пытаемся динамически выделить память printf("Память выделить не удалось!"); //В случае неудачи выводим сообщение, else //а в случае успеха for (int i = 0; i < 100; i++) //заполняем выделенную *(p + i) = i; //область памяти

    2-я строка в этом примере - это как раз та, которую я упоминал в начале статьи.

    В более общем случае, функции, генерирующие некоторые данные, динамически выделяющие под них память, заполняющие её этими данными и возвращающие адрес выделенного участка, могут возвращать NULL и как признак того, что данные сгенерировать не удалось, например, вследствие ошибки в переданных функции параметрах.

    Значение NULL обычно присваивают указателю для того, чтобы отличать его от указателя, содержащего адрес участка памяти, к которому можно обращаться с целью чтения из него информации или записи информации в него. Например, при создании указателя можно сразу присвоить ему значение NULL . В дальнейшем, код может проверить значение этого указателя и сразу же "понять", можно ли обращаться по содержащемуся в нём адресу или нет. Рассмотрим простой пример:

    Int *p = NULL; //Создаём указатель p и присваиваем ему NULL ... //Программный код, в котором указателю p может... //быть (а может и не быть!) присвоен адрес... //некоторой переменной a типа int if (p != NULL) //Если указатель ненулевой, printf("a=%d", *p); //то печатаем значение переменной a else //В противном случае printf("p указывает в никуда!"); //выводим информационное сообщение

    Другой пример: указателю был присвоен адрес динамически выделенного участка памяти. Через некоторое время выделенная память была утилизирована. Теперь обращение по адресу, хранящемуся в указателе, может привести к непредсказуемым последствиям. Чтобы избежать этого, указателю присваивают значение NULL , как индикатор того, что разыменовывать указатель нельзя.

    Кстати, библиотечная функция free() , занимающаяся освобождением динамически выделенной памяти и принимающая в качестве аргумента адрес выделенного участка, корректно обрабатывает значение NULL . Таким образом, если передать ей нулевой указатель, то ничего страшного не произойдёт. Между прочим, не произойдёт вообще ничего!

    В односвязном списке каждый узел, за исключением последнего, связан с последующим. В программной реализации списка узлы обычно представляются переменными структурного типа (для простоты будем эти переменные тоже называть узлами), а упомянутая связь между узлами реализуется следующим образом. Каждый узел содержит в качестве поля указатель на узел, следующий за ним. Исключением является последний узел списка, соответствующему указателю которого указывать не на что. Представляется вполне разумным присвоить ему значение NULL .

    Этот нулевой указатель будет являться признаком того, что узел, в котором он содержится, - последний в списке. Данным признаком очень удобно пользоваться во время перебора всех узлов списка в цикле: мы переходим от узла к узлу, пока не "наткнёмся" на нулевой указатель. На этом цикл заканчивается.

    Пусть, например, тип узла описывается следующим образом:

    Struct node { int element; //Содержимое узла - целое число struct node *next; //Указатель на следующий узел };

    Тогда функция, печатающая на отдельной строке содержимое каждого узла, может выглядеть так:

    //Функция, печатающая содержимое списка //В качестве параметра принимает адрес первого узла списка void print (struct node *list) { do printf("%d\n", list->element); while ((list = list->next) != NULL); }

    Как только указатель на следующий узел окажется равным NULL , итерации прекращаются.

Как мы видим, NULL можно использовать в программе везде, где можно использовать адреса. NULL можно присваивать указателям, возвращать из функций, передавать в функции. Правда, в последнем случае нужно быть уверенным, что функция "умеет" корректно обрабатывать NULL . Например, функция free() таким умением обладает, а приведённая выше функция print() - нет.

А вот что нельзя делать - так это разыменовывать нулевые указатели! Поведение программы в результате выполнения этой операции непредсказуемо. В любом случае, ничего хорошего ожидать не приходится. Эксперименты показывают, что при использовании компилятора MinGW64 в среде Windows 7 операционная система сразу же "убивает" процесс, попытавшийся обратиться по "запрещённому" адресу.

Зададимся вопросом: а можно ли вообще обходиться без макроса NULL , используя вместо него константу, являющуюся его значением? Разумеется, можно, но только для этого нужно её знать. Один из самых простых способов узнать эту константу - вывести NULL на печать, например, следующим образом:

Printf("NULL=%p", NULL);

Здесь мы применили спецификатор формата %p , предназначенный для отображения адресов. В случае использования компилятора MinGW64 результат выполнения данной строки будет следующим:

NULL=00000000

Ну что ж, оказалось, что, по крайней мере, в случае MinGW64, NULL - это ноль!

Другой способ установления значения макроса NULL заключается в нахождении его определения в файле stdlib.h (при условии, что этот файл доступен). Снова обратимся к компилятору MinGW64. В файле stdlib.h , входящем в состав этого компилятора, имеются следующие макроопределения (для удобства восприятия я расставил отступы в началах строк; в оригинале они отсутствуют):

#ifndef NULL #ifdef __cplusplus #ifndef _WIN64 #define NULL 0 #else #define NULL 0LL #endif /* W64 */ #else #define NULL ((void *)0) #endif #endif

Поскольку при использовании языка C99 макрос __cplusplus не определён, актуальным для нас является определение макроса NULL , данное в 9-й строке. Как мы видим, NULL определяется как ноль, приведённый к типу void * .

Логично задаться вопросом: а для чего вообще нужен макрос NULL ? Не проще ли везде и всегда вместо него использовать просто ноль? Ответ: всё дело в переносимости кода. Гипотетически можно допустить существование таких компиляторов, в которых NULL имеет значение, отличное от ноля (хотя я таких компиляторов не встречал). Использование макроса NULL позволит разным компиляторам во время компиляции одного и того же кода заменять этот макрос тем его значением, который соответствует данному компилятору. Если же использовать вместо NULL ноль, то в тех компиляторах, в которых NULL != 0 , скомпилированный код может оказаться неработоспособным, а в худшем случае его выполнение может привести к повреждению расположенных в памяти данных, не имеющих отношения к выполняемой программе.

Лично меня переносимость моего кода на языке C99 совершенно не волнует. Меня заботит лишь его совместимость с тем компилятором, который я использую, а именно - MinGW64. Что касается NULL , то его применение я нахожу неудобным. Куда приятнее, например, писать "if (p) ", чем "if (p != NULL) ". Поэтому я никогда не использую NULL , обходясь вместо него нулём. Причём, я даже не привожу ноль к типу void * , поскольку такое приведение осуществляется компилятором автоматически.

Надеюсь, что читатель вынес для себя что-нибудь полезное из этой статьи и решил, стоит ему использовать макрос NULL , или нет.