TLDR: хотя способность функций «проходить» через неопределенные значения, которые вызывающие абоненты игнорируют, дает преимущества, которые на большинстве платформ намного превышают стоимость, и, следовательно, должны обеспечиваться качественными реализациями, нацеленными на такие платформы, Стандарт не требуетреализации, обеспечивающие его, и, следовательно, «умные» реализации этого не делают.
Существует много конструкций, которые все компиляторы обрабатывали бы последовательно, когда был написан стандарт, но которые стандарт явно не определяет.Стандарт отмечает, что общий способ обработки действий, при которых Стандарт не налагает никаких требований, «задокументированно характерен для окружающей среды», но в обосновании отмечает, что решение о том, когда делать это, является вопросом качества выполнения, а несоответствие.Обоснование также признает, что реализация может соответствовать, хотя и низкого качества, но быть бесполезной, но авторы не считают необходимым тратить усилия на запрещение таких реализаций.
Существует два разумных и полезных способакачественный компилятор для типичной платформы может обрабатывать код, подобный приведенному выше:
Компилятор может перехватывать определенные реализацией средства, если функция пытается вернуть неинициализированный объект, независимо от того,вызывающий код будет использовать значение [код для генерации прерывания может не знать ничего о вызывающем коде].
Компилятор может оставить некоторую произвольную коллекцию битовместо, которое вызывающий абонент может использовать, а может и не использовать, без побочных эффектов, если вызывающий фактически их не использует.Обратите внимание, что если объекты определенного типа не будут иметь биты заполнения при хранении в памяти, они могут иметь биты заполнения при хранении в регистрах и могут вести себя странно, если эти биты заполнения установлены неправильно.
Авторы Стандарта не предпринимали попыток перечислить все, что может сделать реализация при работе с неопределенными значениями, поскольку они полагали, что разработчики, стремящиеся создать качественные реализации, будут решать, какой вариант действий будет наиболее подходящим, учитываяпредполагаемые платформы и цели рассматриваемых реализаций.
К сожалению, несмотря на то, что на любой распространенной платформе практически не будет стоить позволить функциям безопасно возвращать неопределенные значения в тех случаях, когда вызывающие их собираются игнорировать, и вв некоторых случаях это приведет к более эффективному коду, чем было бы возможно в других случаях (например, если сказать, что учитывая:
extern volatile int vv1, vv2, vv3;
int foo(int mode)
{
int result;
vv1 = 1;
if (mode & 1)
result = vv2;
if (mode & 2)
result = vv3;
return result;
}
, оператор "foo (0);" будет хранить 1 в vv1 без других побочных эффектов)cts позволит избежать необходимости заставлять программистов заставлять компиляторы генерировать ненужную нагрузку) разработчикам компиляторов стало модным находить «умные» способы использования факта, что стандарт не требует таких гарантий.Например, приведенный выше код может быть «оптимизирован» для:
int foo(int mode)
{
vv1 = 1;
if (!(mode & 2))
return vv2;
if (mode & 1)
+vv2; // Access and ignore value
return vv3;
}
Независимо от того, будет ли практическая ценность таких «оптимизаций» когда-либо превышать возможность позволить программистам позволять компиляторам избегать ненужных нагрузок, программисты, которые могут 'не нужно быть уверенным, что их код будет выполняться только на качественных реализациях, для которых нужно учесть «умные».