В вычислениях (в частности, в программировании ) неопределенное значение - это условие, при котором выражение не имеет правильного значения , хотя синтаксически верно. Неопределенное значение не следует путать с пустой строкой , логическим значением «ложь» или другими «пустыми» (но определенными) значениями. В зависимости от обстоятельств оценка неопределенного значения может привести к исключению или неопределенному поведению , но в некоторых языках программирования неопределенные значения могут возникать во время нормального, предсказуемого хода выполнения программы .
Языки с динамической типизацией обычно по возможности обрабатывают неопределенные значения явно. Например, в Perl есть undef
оператор [1], который может «присваивать» такое значение переменной. В системах других типов неопределенное значение может означать неизвестное, непредсказуемое значение или просто сбой программы при попытке его оценки. Обнуляемые типы предлагают промежуточный подход; см. ниже .
Умение обращаться
Значение частичной функции не определено, если ее аргумент находится вне области определения . Они включают в себя многочисленные арифметические случаи , такие как деление на ноль , квадратного корня или логарифма о наличии отрицательного числа и т.д. Другим распространенным примером является доступ к массив с индексом , который находится вне границ, как это значение в ассоциативном массиве для ключа , который его не содержит. Существуют различные способы решения этих ситуаций на практике:
Зарезервированная стоимость
В приложениях, где неопределенные значения должны обрабатываться изящно, обычно зарезервировано специальное нулевое значение, которое отличается от нормальных значений. Это решает проблему, создавая определенное значение для представления ранее неопределенного случая. Примеров тому множество:
- Стандартная библиотека ввода-вывода C резервирует специальное значение,
EOF
чтобы указать, что входные данные больше недоступны.getchar()
Функция возвращает следующий доступный входной символ, илиEOF
если нет более доступной. (Код символа ASCII определяет для этой цели нулевой символ , но стандартная библиотека ввода-вывода хочет иметь возможность отправлять и получать нулевые символы, поэтому она определяет отдельноеEOF
значение.) - Стандарт арифметики с плавающей запятой IEEE 754 определяет специальное « нечисловое » значение, которое возвращается, когда арифметическая операция не имеет определенного значения. Примерами являются деление на ноль , или квадратный корень или логарифм из отрицательного числа .
- В языке структурированных запросов есть специальное
NULL
значение для обозначения отсутствующих данных. - Язык Perl позволяет проверять определенность выражения через
defined()
предикат. [2] - Многие языки программирования поддерживают концепцию нулевого указателя, отличного от любого действительного указателя, и часто используются как возврат ошибки.
- Некоторые языки позволяют допускать значение NULL для большинства типов, например C # . [3]
- Большинство системных вызовов Unix возвращают специальное значение -1, указывающее на сбой.
В то время как языки с динамической типизацией часто гарантируют, что неинициализированные переменные по умолчанию имеют нулевое значение, статически типизированные значения часто этого не делают, и различают нулевые значения (которые четко определены) от неинициализированных значений (которые таковыми не являются). [3]
Обработка исключений
В некоторых языках программирования есть концепция обработки исключений для обработки ошибок при возврате значения. Функция возвращает определенным образом, но не возвращает значения, поэтому нет необходимости изобретать специальное значение для возврата.
Вариантом этого является обработка сигналов , которая выполняется на уровне операционной системы и не интегрирована в язык программирования. Обработчики сигналов могут пытаться выполнить некоторые формы восстановления, такие как завершение части вычислений, но без такой гибкости, как полностью интегрированная обработка исключений.
Невозвратные функции
Функция, которая никогда не возвращается, имеет неопределенное значение, потому что значение никогда не может быть обнаружено. Таким функциям формально присваивается нижний тип , не имеющий значений. Примеры делятся на две категории:
- Функции, которые повторяются бесконечно . Это может возникнуть умышленно или в результате поиска чего-то, что никогда не будет найдено. (Например, в случае отказа оператора μ в частично рекурсивной функции .)
- Функции, завершающие вычисления, например exitсистемный вызов . Изнутри программы это неотличимо от предыдущего случая, но имеет значение для инициатора программы.
Неопределенное поведение
Все предыдущие методы обработки неопределенных значений требуют обнаружения неопределенности. То есть вызываемая функция определяет, что она не может вернуть нормальный результат, и предпринимает некоторые действия, чтобы уведомить вызывающего. На другом конце спектра неопределенное поведение возлагает бремя на вызывающего, чтобы избежать вызова функции с аргументами за пределами ее домена. Нет предела тому, что может случиться. В лучшем случае легко обнаруживаемая авария ; в худшем случае - незаметная ошибка в кажущемся несвязанным вычислении.
(Формальное определение «неопределенного поведения» включает в себя еще более экстремальные возможности, включая такие вещи, как « остановиться и загореться » и «заставить демонов вылететь из вашего носа» [4] ).
Классический пример - ссылка на висячий указатель . Разыменовать действительный указатель очень быстро , но может быть очень сложно определить, действителен ли указатель. Поэтому компьютерное оборудование и низкоуровневые языки, такие как C , не пытаются проверять указатели перед их разыменованием, вместо этого передают ответственность программисту. Это обеспечивает скорость в ущерб безопасности.
Неопределенное значение sensu stricto
Строгое определение неопределенного значения - это поверхностно действительный (ненулевой) вывод, который не имеет смысла, но не вызывает неопределенного поведения. Например, передача отрицательного числа в функцию быстрого вычисления вычисления квадратного корня даст число. Не очень полезное число, но вычисление завершится и что-то вернет .
Неопределенные значения особенно часто встречаются в оборудовании. Если провод не несет полезной информации, он все еще существует и имеет определенный уровень напряжения. Напряжение не должно быть аномальным (например, не опасным перенапряжением ), но конкретный логический уровень не важен.
Такая же ситуация возникает в программном обеспечении, когда буфер данных предоставляется, но не полностью заполнен. Например, strftime
функция библиотеки C преобразует метку времени в удобочитаемую форму в предоставленном буфере вывода. Если выходной буфер недостаточно велик для хранения результата, возвращается ошибка и содержимое буфера не определено.
С другой стороны, openсистемный вызов в POSIX принимает три аргумента: имя файла, некоторые флаги и режим файла. Файловый режим используется, только если включены флаги O_CREAT
. обычно используется форма с двумя аргументами open
, которая обеспечивает неопределенное значение для режима файла, если O_CREAT
оно опущено.
Иногда бывает полезно работать с такими неопределенными значениями ограниченным образом. Общее вычисление все еще может быть четко определено, если неопределенное значение позже будет проигнорировано.
Например, язык C позволяет преобразовывать указатель в целое число, хотя числовое значение этого целого числа не определено. Это все еще может быть полезно для отладки, для сравнения двух указателей на равенство или для создания связанного списка XOR .
Безопасная обработка неопределенных значений важна в системах управления оптимистичным параллелизмом , которые обнаруживают состояние гонки постфактум. Например, чтение общей переменной, защищенной seqlock, приведет к неопределенному значению до определения того, что произошло состояние гонки. Затем он отбрасывает неопределенные данные и повторяет операцию. Это дает определенный результат до тех пор, пока операции, выполняемые с неопределенными значениями, не приводят к полноценному неопределенному поведению.
Другими примерами использования неопределенных значений являются генераторы случайных чисел и хеш-функции . Конкретные возвращаемые значения не определены, но они имеют четко определенные свойства и могут использоваться без ошибок.
Обозначение
В теории вычислимости неопределенность выражения обозначается как expr ↑, а определенность как expr ↓.
Рекомендации
- ^ "undef" . Документация Perl 5 . 2009-09-25 . Проверено 26 марта 2010 .
- ^ "определено" . Документация Perl 5 . 2009-09-25 . Проверено 26 марта 2010 .
- ^ а б Карр, Ричард (1 октября 2006 г.). «Числовые типы данных C #, допускающие значение NULL» . Учебник по основам C # . Проверено 27 марта 2010 .
- ^ «Носовые демоны» . Файл жаргона . Проверено 12 июня 2014 .
Смотрите также
- Определенное и неопределенное (математика)
- Нулевой (SQL)