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