Но есть случаи, в которых делаются некоторые допущения по поведению. Случаи unspecified behavior и undefined behavior перепутать легче всего.
Unspecified behavior. Неспецифицированное поведение. Система может реализовать любое из поведений (по большей части для случаев unspecified behavior, Стандарт предлагает несколько поведений на выбор), не должна говорить какое именно реализовано и даже не обязательно, чтобы она вела себя в таких ситуациях одинаково внутри одной программы или функции. При этом предполагается, что на вход была подана правильная (well-formed) программа, соответсвующая синтаксическим, семантическим и прочим правилам языка.
Например: все аргументы функции должны быть вычислены до вызова функции, но они могут быть вычислены в любом порядке. Система не должна выбирать какой-то определенный порядок и не должна указывать по каким правилам она этот порядок выбирает, чтобы его можно было предугадать.
Undefined behavior. Неопределенное поведение. Это поведение может возникать только как реакция на неправильную программу. Далеко не все неправильные конструкции могут вызвать такое поведение, большинство ошибок требуют вполне определенную диагностику.
Undefined behavior означает, что стандарт не накладывает каких-либо ограничений. Может случиться все, что угодно.
Например: разыменование указателя, который равен NULL, может дать 0, или любое произвольное значение, или остановку программы, или сигнал какого-либо вида, или исключение, или реализация может послать email вашему боссу с рассказом о том, какой вы неаккуратный программист. Или все вместе. Или что-то еще.
По большому счету получается, что unspecified behavior означает "как будет работать толком неизвестно, но все будет хорошо". Если оно случается, то это, как правило, нормально и не стоит по его поводу беспокоиться. А undefined behavior означает "как будет работать толком неизвестно, но все будет плохо". И надо от него срочно избавляться, если для его присутствия в программе нет неких загадочных причин.
Это не все поведения, есть еще, но в отличие от двух предыдущих по их названиям можно ясно себе представить, что они означают:
Implementation-defined behavior. Поведение, зависящее от реализации. Похоже на unspecified behavior, но в документации к системе должно быть указано, какое именно поведение реализовано. И на это поведение можно полагаться.
Например: результат x%y, где x и y целые, а y отрицательное, может быть как положительным, там и отрицательным, но в документации к системе должно быть написано каким именно он будет.
Locale-specific behavior. Поведение, зависящее от локали. Причем речь тут идет не только о языке. Стандарт говорит о "национальных обычаях, культуре и языке". Поведение должно быть документировано.
Например: должна ли функция islower возвратить true для символов, не входящих в 26 маленьких латинских букв.
Ссылки по теме:
1996 С++ Drawft Standarts - Definitions
Unspecified versus undefined behavior
Technorati tag: cpp